【问题标题】:Kill fork on windows throws "write EPIPE"Windows 上的 Kill fork 抛出“写 EPIPE”
【发布时间】:2015-07-23 14:08:01
【问题描述】:

我想在特定时间后杀死分叉。但是,在我的代码库中,有时会出现以下错误(仅在 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)

这个错误似乎发生在工作人员尚未完全启动并被杀死时(例如需要 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 之类的东西,我就没有问题,所以我怀疑这是因为我的工人还没有完成“启动”。

奇怪的是,我有时也会得到一个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)

【问题讨论】:

    标签: node.js pipe fork broken-pipe


    【解决方案1】:

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

    解决方法是等待listening事件再杀叉。

    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);
    }
    

    【讨论】:

      【解决方案2】:

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

      所以不要从主进程中杀死工作人员,而是从主进程向工作人员发送一条消息,并在工作人员中使用process.exit() 语句来杀死自己。

      这样,worker 将完成当前的工作并听取主进程的消息并杀死自己。

      更新

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

      希望对你有帮助!!

      【讨论】:

      • 你能举个例子吗? process.exit 会优雅地完成它吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 2014-01-02
      • 2014-12-26
      • 2015-08-17
      • 1970-01-01
      • 2015-07-14
      相关资源
      最近更新 更多