2016-05-03 3 views
9

EDIT 2уродовать сбой после запуска child_process.execFile

я «решил» проблему, но я не хочу, чтобы опубликовать его в качестве ответа б/с это не объясняет, что на самом деле произошло. В коде для .NET resourceReader.exe Я использую

Console.OutputEncoding = System.Text.Encoding.UTF8; 

для вывода многоязычных ресурсов для stdout в юникод. Если сбросить кодировку в конце моей программы с

Console.OutputEncoding = System.Text.Encoding.Default; 

тогда я не получаю никаких ошибок в узле. Если я не сброшу его, я получаю ошибку, описанную в исходном вопросе. Похоже, что .NET каким-то образом испортил некоторые настройки выходного кодирования на cmd.exe и заставило последующий запуск узла сбой!

EDIT

я сузил ошибку, вызвано resourceReader.exe. Это программа .NET, которая считывает некоторые потоки ресурсов из сборки .NET и выводит их на stdout с помощью Console.WriteLine. Я добавил Console.OutputEncoding = System.Text.Encoding.UTF8 в resourceReader.exe, потому что некоторые из ресурсов находятся в буквах без ASCII, и это то, что вызывает крах ворчания!

Если я выхожу из этой строки, задача не падает, но ресурсы отображаются в непечатаемых символах ASCII! Кроме того, авария происходит только в том случае, если я на самом деле печатаю не-ASCII в sdtout. Если я их не печатаю, это не ошибка.

ORIGINAL

Я добавил шаг к моей Gruntfile, который использует child_process.execFile для запуска при чтении данных из внешней программы и использует его в сборке. Теперь, когда я запускаю свою сборку, она работает отлично в первый раз, но во второй раз сбивается!

Вот выход из аварии (это во время уродовать задачи):

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) 

Вот код для выполнения этой задачи, которая использует 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; 
    } 

Вот некоторые вещи, я открыл отладки, которые могут быть полезны

  1. Если перенаправить вывод хрюкать (с использованием либо > filename или | process) он работает нормально
  2. Когда я перенаправить вывод, I никогда не см. сообщение от uglify, что он создал основной вывод только тем, что он создал исходную карту.
  3. Если закрыть и снова открыть свою командную строку (cmd.exe) она отлично работает
  4. Я добавил слушателя к exit и close событий дочернего процесса с использованием rdr.on("close", function() { console.log("close"); }); и то же самое для выхода. Оба события срабатывают, как ожидалось, в первом прогоне.
  5. Используя Process Explorer, я вижу, как node.exe открывается в командной строке и закрывается снова, когда моя команда завершается.В командной строке нет процессов, видимо «оставленных открытыми».
+0

Я думаю, что ваша программа все еще работает в фоновом режиме после первого вызова Grunt, используйте htop для подтверждения. –

+1

@RaNdoM_PoWneD Я нахожусь в Windows. Я не вижу, чтобы он работал в диспетчере процессов. –

+0

Очень жаль, что у меня нет дальнейшей идеи:/ Я чувствую, что что-то не заканчивается хорошо (как открытая труба, сокет ...), которые блокируют запуск нового экземпляра. Удачи –

ответ

0

То, что трассировка стека в конечном счете показывает ошибку socket.write, является интересной. Ничто в коде, который вы указали, не предполагает, что вы пытаетесь записать в сокет.

Если мы следуем за стеком, мы можем видеть, что на самом деле это ворчание, которое пытается записать в сокет, поскольку оно пытается зарегистрировать неперехваченное исключение.

Итак, сначала ваша задача с ворчами выдает неизвестную в настоящее время ошибку, а затем ругается сама по себе, потому что она не может рассказать вам об этом.

Сначала я попытался бы зарегистрировать ошибку, которая возникает в вашем дочернем процессе. В настоящее время, если есть ошибка, вы просто throw, не выясняя, что это такое. Вероятно, это то, что пытается ворчать и не удается войти в систему.

Заменить

if (err) throw new Error(err);

С

if (err) console.error(err);

это, мы надеемся избежать socket.write проблему и дать вам конкретную информацию о том, что ошибка происходит на дочернем процессе. Что ты видишь?

Во-вторых, я бы постарался использовать child_process.exec вместо child_process.execFile. Это создаст оболочку и запустит внутри нее resourceReader.exe (вместо того, чтобы запускать ее напрямую). Это может помочь избежать любых проблем, с которыми вы сталкиваетесь с командой, выполняющейся/выполняющейся в фоновом режиме, что может быть причиной ошибки socket.write.

+0

Моя прочитанная задача культуры запускает * после * задачу uglify. Я попробовал ваше предложение, и оно не изменило выход. –

Смежные вопросы