使用套接字优雅地处理分叉进程中未捕获的异常

Gracefully handle uncaught exception in forked process with a socket

我无法找到一种方法来正确处理当已向其发送套接字的分叉进程失败时的情况。

这里是 server.js 的例子:

'use strict';

var http = require('http');
var fork = require('child_process').fork;

var srv = http.createServer(function (req, res) {
  var f = fork('./client.js');
  f.send('socket', res.socket);
});

srv.listen(7331, 'localhost', function () {
  console.log('server started');

  var req = http.request({
    port: 7331,
    path: '/'
  }, function (res) {
    res.setEncoding('utf8');
    var body = '';
    res.on('data', function (chunk) {
      body += chunk;
    });
    res.on('end', function () {
      console.log('RESPONSE', res.statusCode, res.headers, body);
    });
  });
  req.on('error', function (e) {
    console.log('REQUEST ERROR', e.stack);
  });
  req.end();
});

client.js的:

throw new Error('Client error');

我得到以下输出:

    server started
client.js:1
(function (exports, require, module, __filename, __dirname) { throw new Error('Client Error');
                                                              ^

Error: Client Error
    at Object.<anonymous> (client.js:1:69)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:457:10)
    at startup (node.js:136:18)
    at node.js:972:3
REQUEST ERROR Error: socket hang up
    at createHangUpError (_http_client.js:209:15)
    at Socket.socketOnEnd (_http_client.js:294:23)
    at emitNone (events.js:72:20)
    at Socket.emit (events.js:166:7)
    at endReadableNT (_stream_readable.js:905:12)
    at doNTCallback2 (node.js:450:9)
    at process._tickCallback (node.js:364:17)

是否可以在给定情况下处理分叉进程中的未捕获异常并生成带有状态代码和正文中错误描述的友好响应?

我尝试过的:

  1. 订阅了 child 在 server.jsclose 事件并从那里发送了没有运气的响应 - This socket is closed. 被抛出
  2. 在抛出错误之前在 client.js 中做了一些准备:订阅了 uncaughtException 并向套接字发送了一些响应数据 - 仍然 socket hang up 并且没有响应

由于此处 activity 不存在,我将问题发布在 nodejs 存储库 https://github.com/nodejs/node/issues/4745 中,并引起了 nodejs 贡献者的关注。

总结:在发送给子进程的父进程中使用套接字是不可能的,因为一旦调用 send() 它就会被销毁。

所以解决问题的唯一方法就是在client.js错误发生之前做一些准备。我在 try #2 中指出我这样做了,但也许我做错了......使用以下 client.js 代码,一切正常:

'use strict';

let socket;

process.on('uncaughtException', function (e) {
  socket.write(`HTTP/1.1 500 OK\nContent-Type: text/html\nContent-Length: ${e.message.length}\n\n${e.message}`);
});

process.on('message', function (type, s) {
  socket = s;
  routine();
});


function routine() {
  throw new Error('Client error');
}