在 windows 上杀死叉子抛出 "write EPIPE"

Kill fork on windows throws "write EPIPE"

我想在特定时间后杀死叉子。但是,在我的代码库中,有时会出现以下错误(仅在 windows 上):

events.js:85
      throw er; // Unhandled 'error' event
            ^
Error: write EPIPE
    at exports._errnoException (util.js:746:11)
    at ChildProcess.target._send (child_process.js:484:28)
    at ChildProcess.target.send (child_process.js:416:12)
    at sendHelper (cluster.js:676:8)
    at send (cluster.js:512:5)
    at cluster.js:488:7
    at SharedHandle.add (cluster.js:99:3)
    at queryServer (cluster.js:480:12)
    at Worker.onmessage (cluster.js:438:7)
    at ChildProcess.<anonymous> (cluster.js:692:8)

每当 worker 尚未完全启动并被杀死时(例如需要 1 秒启动并在启动前被杀死),似乎都会发生此错误

这是一个最小的示例,以便您可以重现。

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

var workers=[];

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        workers[i] = cluster.fork();
        console.log('forking');
    }

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });

    setTimeout(function(){
        workers.forEach(function(worker){
            worker.kill();
        })
    },1)

} else {
    // Workers can share any TCP connection
    // In this case its a HTTP server
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
    }).listen(8000);
}

如果我将 http.createServer 更改为 console.log 之类的东西,我没有问题,所以我怀疑这是因为我的工人还没有完成 "starting"。

奇怪的是,我有时也会得到一个 AssertionError(它们似乎不是任何一种模式,我有时连续 10 次出现相同的错误,有时它会在两个错误:EPIPE 和 ASSERTION 错误之间似乎是随机的。

assert.js:86
  throw new assert.AssertionError({
        ^
AssertionError: Resource leak detected.
    at removeWorker (cluster.js:346:9)
    at ChildProcess.<anonymous> (cluster.js:366:34)
    at ChildProcess.g (events.js:199:16)
    at ChildProcess.emit (events.js:110:17)
    at Process.ChildProcess._handle.onexit (child_process.js:1074:12)

错误的原因是当我们发送 SIGTERM 信号时守护进程还没有监听:

解决方法是等待 listening 事件,然后再杀死 fork。

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

var workers=[];

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        workers[i] = cluster.fork();
        console.log('forking');
    }

    cluster.on('listening', function(worker, code, signal) {
        setTimeout(function(){
            worker.kill();
        },1)
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });



} else {
    // Workers can share any TCP connection
    // In this case its a HTTP server
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
    }).listen(8000);
}

这是我的解决方法... 正如 edi9999 所说,工作进程正在忙于某事,你不能在它不听的时候杀死它。

因此,与其从主进程中杀死 worker,不如从主进程向 worker 发送一条消息,并在 worker 中使用 process.exit() 语句来杀死自己。

这样,worker会完成当前的工作,监听主进程的消息,然后kill自己。

更新

在我的这个 Repository 中,有一个示例代码,您可以尝试一下。这是一个命令行工具。如果您进入该文件夹并输入 node se 并按回车键。您将获得有关如何使用它的说明。 如果你只是想看代码。同时查看以下两个文件。 1. se.js 2.functions.js

希望对您有所帮助!!