uglify运行child_process.execFile后崩溃

jus*_*mer 9 .net c# child-process node.js gruntjs

编辑2

我"解决"了这个问题,但我不想把它作为答案发布b/c它不能解释实际发生了什么.在resourceReader.exe我使用的.NET代码中

Console.OutputEncoding = System.Text.Encoding.UTF8;
Run Code Online (Sandbox Code Playgroud)

将国际化资源输出到stdoutunicode.如果我在程序结束时重置编码

Console.OutputEncoding = System.Text.Encoding.Default;
Run Code Online (Sandbox Code Playgroud)

那么我在Node中没有任何错误.如果我没有重置它,我会收到原始问题中描述的错误.似乎.NET在某种程度上弄乱了一些输出编码设置cmd.exe并导致后续节点运行失败!

编辑

我把错误缩小到了原因resourceReader.exe.它是一个.NET程序,它从.NET程序集中读取一些资源流,并使用它们将它们打印到stdout Console.WriteLine.我添加Console.OutputEncoding = System.Text.Encoding.UTF8了resourceReader.exe因为一些资源是非ASCII字母,这是什么导致崩溃的咕噜声!

如果我取出该行,任务不会崩溃,但资源以不可打印的ASCII字符显示!此外,只有在我实际打印非ASCII到sdtout时才会发生崩溃.如果我不打印它们,它不会出错.

原版的

我在我的Gruntfile中添加了一个步骤,用于child_process.execFile从外部程序运行读取一些数据并在构建中使用它.现在每当我运行我的构建时,它第一次运行正常,但第二次崩溃!

这是崩溃的输出(这是在uglify任务期间):

File build/Scripts/NDB.contacts.min.js created: 16.85 kBevents.js:85
  throw er; // Unhandled 'error' event
        ^
Error: This socket is closed.
  at WriteStream.Socket._writeGeneric (net.js:656:19)
  at WriteStream.Socket._write (net.js:709:8)
  at doWrite (_stream_writable.js:301:12)
  at writeOrBuffer (_stream_writable.js:288:5)
  at WriteStream.Writable.write (_stream_writable.js:217:11)
  at WriteStream.Socket.write (net.js:634:40)
  at Log._write (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:161:26)
  at Log.wrapper [as _write] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
  at Log._writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:166:8)
  at Log.wrapper [as _writeln] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
  at Log.writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:177:8)
  at Log.wrapper (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
  at writeln (C:\...\node_modules\grunt\lib\grunt\fail.js:30:13)
  at Object.fail.fatal (C:\...\node_modules\grunt\lib\grunt\fail.js:46:3)
  at process.uncaughtHandler (C:\...\node_modules\grunt\lib\grunt.js:121:10)
  at process.emit (events.js:129:20)
  at process._fatalException (node.js:236:26)
  at Task.runTaskFn (C:\...\node_modules\grunt\lib\util\task.js:250:7)
  at Task.<anonymous> (C:\...\node_modules\grunt\lib\util\task.js:293:12)
  at C:\...\node_modules\grunt\lib\util\task.js:220:11
  at process._tickCallback (node.js:355:11)
Run Code Online (Sandbox Code Playgroud)

这是使用child_process的任务的代码.

    function readAllCultures() {
        var readDeferred = q.defer();

        childProc.execFile("../tools/resourceReader.exe", function (err, stdout, stderr) {
            if (err) throw new Error(err);

            var cultures = JSON.parse(stdout);
            readDeferred.resolve(cultures);
        });

        return readDeferred.promise;
    }
Run Code Online (Sandbox Code Playgroud)

这是我发现调试的一些可能有用的东西

  1. 如果我重定向grunt的输出(使用> filename或者| process)它运行正常
  2. 当我重定向输出时,我从未看到来自uglify的消息,它创建了主要输出,只是它创建了源地图.
  3. 如果我关闭并重新打开我的命令提示符(cmd.exe)它工作正常
  4. 我添加了一个监听器exit和close子进程的事件使用rdr.on("close", function() { console.log("close"); });和退出相同的事件.这两个事件在第一轮中都按预期触发.
  5. 使用Process Explorer,我可以node.exe在命令提示符下看到open,并在命令完成运行时再次关闭.在命令提示符下没有明显"保持打开"的进程.

dun*_*all 0

堆栈跟踪最终显示错误的事实socket.write很有趣。您提供的代码中没有任何内容表明您正在尝试写入套接字。

如果我们跟踪堆栈,我们可以看到实际上是 grunt 正在尝试写入套接字,因为它正在尝试记录未捕获的异常。

因此,首先您的 grunt 任务会抛出一个当前未知的错误,然后 grunt 本身也会出现错误,因为它无法告诉您相关信息。

我首先尝试记录您的子进程中发生的错误。目前,如果出现错误,您只需简单地throw处理它,而无需找出错误​​是什么。这很可能就是 grunt 正在尝试但未能记录的内容。

代替

if (err) throw new Error(err);

和

if (err) console.error(err);

这有望避免该socket.write问题,并为您提供有关子进程上发生的错误的具体信息。你看到了什么?

其次,我会尝试使用child_process.exec而不是child_process.execFile. 这将生成一个 shell 并resourceReader.exe在其中运行(而不是直接运行它)。这可能有助于避免您遇到命令仍在后台运行/失败的任何问题,这可能是错误的原因socket.write。