2016-05-03 33 views
9

EDIT 2uglify crash dopo l'esecuzione child_process.execFile

I "risolto" il problema, ma io non voglio inviare come risposta b/c non spiega cosa è effettivamente accaduto. Nel codice per .NET resourceReader.exe che uso

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

per emettere le risorse internazionalizzati per stdout in unicode. Se a reimpostare la codifica alla fine del mio programma con

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

allora io non capisco eventuali errori nel nodo. Se non lo ripristino, ottengo l'errore descritto nella domanda originale. Sembra che .NET stia in qualche modo rovinando alcune delle impostazioni di codifica di output su e causando il fallimento della successiva esecuzione del nodo!

EDIT

ho ristretto verso il basso l'errore di essere causata da resourceReader.exe. È un programma a.NET che legge alcuni flussi di risorse dall'assembly .NET e li stampa sullo stdout utilizzando Console.WriteLine. Ho aggiunto Console.OutputEncoding = System.Text.Encoding.UTF8 a resourceReader.exe perché alcune delle risorse sono in lettere non ASCII e questo è ciò che causa lo schianto in grugnito!

Se tengo fuori questa linea, l'attività non si blocca, ma le risorse appaiono in caratteri ASCII non stampabili! Inoltre, l'arresto anomalo si verifica solo se in realtà stampo non ASCII in sdtout. Se non li stampo, non fa errore.

ORIGINALE

ho aggiunto un passo alla mia Gruntfile che utilizza child_process.execFile per eseguire una lettura di alcuni dati da un programma esterno e lo utilizza nella build. Ora ogni volta che eseguo la mia build, funziona alla perfezione la prima volta, ma si blocca per la seconda volta!

Ecco l'uscita dal crollo (questo è durante il compito 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) 

Ecco il codice per l'operazione che usa 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; 
    } 

Ecco alcune cose che ho scoperto di debug che potrebbero essere utili

  1. Se reindirizzare l'output di grugnito (utilizzando > filename o | process) funziona benissimo
  2. Quando ho reindirizzare l'output, I non vedere mai il messaggio da brutto che ha creato l'uscita principale solo che ha creato la mappa di origine.
  3. Se chiudo e riapro la mia prompt dei comandi (cmd.exe) funziona bene
  4. ho aggiunto un ascoltatore alle exit e close eventi del processo figlio utilizzando rdr.on("close", function() { console.log("close"); }); e lo stesso per l'uscita. Entrambi gli eventi si attivano come previsto nella prima esecuzione.
  5. Utilizzando Process Explorer, posso vedere node.exe aperto sotto il prompt dei comandi e chiudere di nuovo quando il mio comando termina l'esecuzione.Non ci sono processi visibilmente "lasciati aperti" sotto il prompt dei comandi.
+0

Penso che il tuo programma sia ancora in esecuzione in background dopo la tua prima chiamata Grunt, usa htop per confermare. –

+1

@RaNdoM_PoWneD Sono su Windows. Non lo vedo in esecuzione in Process Manager. –

+0

Scusa, non ho più idea:/ Mi sembra che qualcosa non sia terminato correttamente (come una pipe aperta, un socket ...) che blocca la nuova istanza da eseguire. Buona fortuna –

risposta

0

Il fatto che la traccia dello stack mostri in definitiva un errore socket.write è interessante. Nulla nel codice che hai fornito suggerisce che stai provando a scrivere su un socket.

Se seguiamo lo stack in basso, possiamo vedere che è in realtà un grunt che sta tentando di scrivere su un socket, poiché sta tentando di registrare un'eccezione non rilevata.

Quindi, prima il tuo task grugnito genera un errore attualmente sconosciuto, e quindi grugnisce gli errori perché non può parlarne.

Vorrei innanzitutto provare e registrare l'errore che si verifica nel processo figlio. Attualmente se c'è un errore presente, è semplicemente throw senza scoprire di cosa si tratta. È probabile che questo è ciò che grunt sta provando e non riuscendo a registrare.

Sostituire

if (err) throw new Error(err);

Con

if (err) console.error(err);

Questo si spera di evitare il problema socket.write e vi darà informazioni specifiche su ciò che l'errore sta accadendo sul processo figlio. Cosa vedi?

In secondo luogo, proverei a utilizzare child_process.exec anziché child_process.execFile. Questo genererà una shell ed eseguirà resourceReader.exe al suo interno (invece di eseguirlo direttamente). Ciò potrebbe aiutare a evitare qualsiasi problema riscontrato con il comando ancora in esecuzione/in errore in background, che potrebbe essere la causa dell'errore socket.write.

+0

L'attività di coltura di lettura avvia * dopo * l'attività di uglify. Ho provato il tuo suggerimento e non ha apportato alcuna modifica all'output. –

Problemi correlati