node.js - 执行 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);
});
解决方案
发布答案以防其他人偶然发现此问题(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 中工作。
推荐阅读
- angular - 如何在角度 7 中对 getCurrentNavigation().extras.state 进行单元测试
- google-apps-script - 如何使用 urlfetchapp 登录到具有多页弹出登录表单的网站
- github - 选项卡部分不显示在 github 页面中
- java - 如何使用 Spring 配置文件来模拟实现相同接口的不同服务
- android - 在 DatabindingExpression 中实例化一个列表
- google-chrome - Chrome 和 Firefox 认为第三方 cookie 的规则是什么?
- view - SwiftUI 中的数据流与@EnvironmentObject
- shopify - 如何在单独的标签中显示 Shopify 产品项目变体?
- regex - Bash 是否支持非贪婪正则表达式?
- python - Python根据if条件更新列