【问题标题】:Why is my Node child process that I created via spawn() hanging?为什么我通过 spawn() 创建的 Node 子进程挂起?
【发布时间】:2014-01-14 13:23:06
【问题描述】:

我正在使用 spawn() 进行 git 调用。有时它可以正常工作,但有时它似乎挂起。我没有看到任何事件触发(错误、退出、关闭),但我看到了该过程确实成功完成的证据。

var spawn = require('child_process').spawn;

spawn('git', ['push', 'origin', 'master'])
  .on('error', function(error) {
    console.log("ERROR: DETAILS: " + error);
  })
  .on('close', function(code) {
    console.log("SUCCESS: CODE: " + code);
  })
  .on('exit', function(code) {
    console.log("EXIT: CODE: " + code);
  })

【问题讨论】:

    标签: node.js spawn


    【解决方案1】:

    事实证明,一旦 stderr 缓冲区超过 24kb,您必须从中读取,否则您将看不到任何完成事件。可能的解决方法:

    1. 在 spawn 调用中设置 stdio 选项。

      spawn('git', ['push', 'origin', 'master'], {stdio: 'ignore'});
      

      请参阅 Node ChildProcess 文档了解所有可能性 - 有很多。

    2. 添加一个 on(data) 处理程序。

      var git = spawn('git', ['push', 'origin', 'master']);
      ...
      git.stderr.on('data', function(data) {
        // do something with it
      });
      
    3. 通过管道将其传输到标准输出/标准错误。这对您的应用程序来说可能过于冗长,但为了完整性而将其包含在内。

      var git = spawn('git', ['push', 'origin', 'master']);
      ...
      git.stderr.pipe(process.stderr);
      git.stdout.pipe(process.stdout);
      

    【讨论】:

    • this Node issue 中包含一个可重现的案例。我相信 exit 不会触发这一事实是一个错误,因为缓冲区的大小会导致不同的行为。
    • 事实证明,这正是使用子进程时的方式。您必须对 stdio 管道做一些事情,否则会冒着子进程挂起的风险,因为它的管道已满。另见this thread
    • 在这种情况下,孩子没有挂,它已经退出了。但是,节点代码不接收任何事件。我在子进程消失的地方看到了同样的事情,但是节点从不触发退出或关闭事件,并且我的节点代码死锁等待发生的事情不会发生。对我来说,错误是间歇性的,并不是 100% 可靠地重现。
    猜你喜欢
    • 2011-11-26
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多