child_process.spawnSync()のoptions引数

child_process.spawnSync()で色々書いていたら、3回目で落ちたりすることがわかった。突き詰めていくとどうやら第三引数を再利用していると落ちることがあるようだ。イシュー立てたらすぐ修正された。どうやら内部でoptionsを上書きしてしまっていただけらしい。

io.js v1.0.3上では以下のようなコードで再現できる。

var spawnSync = require('child_process').spawnSync;

var ls;
var opts = {
  stdio: 'inherit'
};

ls = spawnSync('ls', [], opts);
ls = spawnSync('ls', [], opts);
ls = spawnSync('ls', [], opts);

実行すると3回目の`spawnSync()`で例外を吐いて落ちる。

~/Desktop $ iojs test.js
desktop.ini test.js
desktop.ini test.js
child_process.js:905
      throw new TypeError('Incorrect value for stdio stream: ' +
            ^
TypeError: Incorrect value for stdio stream: { type: 'fd', fd: { type: 'fd', fd: 0 } }
    at child_process.js:905:13
    at Array.reduce (native)
    at _validateStdio (child_process.js:829:17)
    at spawnSync (child_process.js:1251:19)
    at Object.<anonymous> (c:\Users\Kyo\Desktop\test.js:13:10)
    at Module._compile (module.js:446:26)
    at Object.Module._extensions..js (module.js:464:10)
    at Module.load (module.js:341:32)
    at Function.Module._load (module.js:296:12)
    at Function.Module.runMain (module.js:487:10)

io.jsではすぐ直りそう(Node.jsではstableに来る頃には直っていることだろう)だが、それまではoptionsはいちいち書いた方が無難だろう。具体的にはJSON.parse(JSON.stringify(opts))とオブジェクトをクローンするテクニックを利用して指定するのが安定して良さそうだ。