首页 > 解决方案 > 执行 child_process.fork 时 Linux 中的 NodeJS 错误?

问题描述

我无法可靠地让分叉子进程向父进程发送超过 219262 字节的消息。

该问题仅在Linux上。在 Windows 中,它按预期工作。这个问题似乎是在 Node 版本 1.0.1 和 1.0.2 之间引入的——在 1.0.1 之前的 Node 版本上运行良好,但在之后的版本就不行了

maxBuffer选项与 child_process.fork 无关,仅适用于 child_process.exec 和 child_process.execFile)

下面是失败的样本。在 Linux 上如果超过 219262 字节,在命令行执行“node parent”将无法输出孩子的“messageToParent” 。

parent.js 是:

var cp = require('child_process');
var child = cp.fork('./child', [], {});

console.log('>>>PARENT ---> SENDING MESSAGE TO CHILD');
child.send({});

child.on('message', function(msg) {
  console.log('>>>PARENT ---> MESSAGE RECEIVED FROM CHILD = ' + JSON.stringify(msg));
});
child.on('error', function(err) {
  console.log('>>>PARENT ---> ERROR FROM CHILD. err = '+ err);
});
child.on('exit', function(code, signal) {
  console.log('>>>PARENT ---> EXIT FROM CHILD. code='+code+' signal = '+ signal);
});
child.on('close', function(code, signal) {
  console.log('>>>PARENT ---> CLOSE FROM CHILD. code='+code+' signal = '+signal);
});
child.on('disconnect', function() {
  console.log('>>>PARENT ---> DISCONNECT FROM CHILD');
});

child.js 是

process.on('message', function(messageFromParent) {

  console.log('>>>>>>CHILD ---> RECEIVED MESSAGE FROM PARENT');
  var messageToParent = "It would be too long to post on stackoverflow, but if I make this string longer than 219262 bytes, it fails to return to the parent in Linux. There is no such issue in Windows";                                                                                                  
  var ret = process.send(messageToParent);
  console.log('>>>>>>CHILD ---> SENDING MESSAGE TO PARENT process.send returned ' + ret);
  process.exit(0);
});

process.on('uncaughtException', function(err) {
  process.send({ output: {ERROR:err} });
  process.exit(-1);
});

标签: node.jsforkchild-process

解决方案


发布答案以防其他人偶然发现此问题(https://github.com/nodejs/node/issues/36268

上面的 child.js 在 1.0.1 之前的 Node 版本中可以完美运行,因为child_process.fork( ) 曾经是同步的。所以"process.send(messageToParent)"后跟"process.exit(0)"将始终将messageToParent返回给 parent.js。然而,在更高版本的 Node 中,process.send()是异步的。因此,子进程必须在 process.send 回调中通过process.exit()退出,否则 V8 javascript 线程和 IPC 管道之间会产生竞争条件。

另外 - 在 Windows 中,默认的 IPC 管道缓冲区足够大,以至于消息总是在子退出之前返回给父级。在 Linux 中情况并非如此。这解释了为什么上面的代码即使在 process.send() 是异步的更高版本的 Node 中也能在 Windows 中工作。


推荐阅读