2016-03-16 12 views
6

Ho un'app di elettroni che utilizza child_process.exec per eseguire attività a esecuzione prolungata. Sto faticando a gestire quando l'utente esce dall'app durante tali attività.Electron kill child_process.exec

Se escono dalla mia app o chiudi chiudi i processi figli continuano a funzionare fino a quando non terminano comunque la finestra dell'app electron è già chiusa e chiusa.

C'è un modo per informare l'utente che ci sono processi ancora in esecuzione e quando hanno finito quindi chiudere la finestra dell'app?

Tutto quello che ho nelle mie main.js è il codice standard:

// Quit when all windows are closed. 
    app.on('window-all-closed', function() { 
    // On OS X it is common for applications and their menu bar 
    // to stay active until the user quits explicitly with Cmd + Q 
    if (process.platform != 'darwin') { 
     app.quit(); 
    } 
    }); 

Dovrei essere l'aggiunta di un assegno da qualche parte?

Grazie per il vostro aiuto

CURA

io non riesco a ottenere il PID del child_process fino al termine. Questo è il mio codice child_process

var loader = child_process.exec(cmd, function (error, stdout, stderr){ 
     console.log(loader.pid) 
     if (error) { 
     console.log(error.message); 
     } 
     console.log('Loaded: ', value) 

Dovrei cercare di farlo in un modo diverso?

+0

Qual è il comportamento desiderato, per uccidere automaticamente il processo figlio quando l'app viene chiusa o in realtà lasciarlo continuare fino al completamento e quindi chiudere automaticamente? – mscdex

+0

@mscdex sarebbe bello uccidere tutti i processi figli e uscire dall'app Sarebbe possibile? – tjmgis

+0

Inoltre, dovresti ottenere i pid ogni volta che chiami i "processi figli" e li uccidi. – shriek

risposta

2

ChildProcess emette un evento exit quando il processo è finito - se tenere traccia dei processi in corso in un array, e li hanno essi stessi rimuovere dopo l'evento exit, si dovrebbe essere in grado di appena foreach su quelli restanti in esecuzione ChildProcess.kill() quando esci dall'app.

Questo potrebbe non essere il 100% codice di lavoro/non il modo migliore di fare le cose, dato che non sono in grado di testarlo proprio ora, ma dovrebbe essere sufficiente per impostare la giusta direzione.

var processes = []; 

// Adding a process 
var newProcess = child_process.exec("mycommand"); 
processes.push(newProcess); 
newProcess.on("exit", function() { 
    processes.splice(processes.indexOf(newProcess), 1); 
}); 

// App close handler 
app.on('window-all-closed', function() { 
    if (process.platform != 'darwin') { 
    processes.forEach(function(proc) { 
     proc.kill(); 
    }); 

    app.quit(); 
    } 
}); 

EDIT: Come Shreik menzionato in un commento, si potrebbe anche solo memorizzare i PID nella matrice invece dei ChildProcess oggetti, quindi utilizzare process.kill(pid) per ucciderli. Potrebbe essere un po 'più efficiente!

+0

continuavo a ricevere un errore dicendo proc.kill(); non era una funzione – tjmgis

9

Quindi, dopo tanti grandi commenti, ho potuto aggiornare il mio codice con un numero di aggiunte per farlo funzionare, quindi sto postando i miei aggiornamenti per tutti gli altri.

1) Variazione da child_process.exec a child_process.spawn

var loader = child_process.spawn('program', options, { detached: true })

2) Utilizzare l'Electron ipcRenderer di comunicare da mio modulo allo script main.js. Questo mi permette di inviare il PID per main.js

ipcRenderer.send('pid-message', loader.pid);

ipcMain.on('pid-message', function(event, arg) { 
    console.log('Main:', arg); 
    pids.push(arg); 
}); 

3) Aggiungi questi PID di serie

4) Nei miei main.js ho aggiunto il seguente codice per uccidere tutti i PID che esistono nell'array prima di uscire dall'app.

// App close handler 
app.on('before-quit', function() { 
    pids.forEach(function(pid) { 
    // A simple pid lookup 
    ps.kill(pid, function(err) { 
     if (err) { 
      throw new Error(err); 
     } 
     else { 
      console.log('Process %s has been killed!', pid); 
     } 
    }); 
    }); 
}); 

Grazie per l'aiuto di tutti.

0

Un'altra soluzione. Se si desidera continuare a utilizzare exec()

Per interrompere il processo figlio eseguito da exec() dare un'occhiata al modulo ps-tree. Esaminano ciò che sta accadendo.

in UNIX, un processo può risolvere utilizzando la chiamata di uscita, ed è processo padre può attendere che tale evento utilizzando la chiamata di sistema wait. la chiamata di sistema di attesa restituisce l'identificatore di processo di un figlio terminato , in modo che il genitore indichi quale dei possibili molti bambini ha terminato . Se il genitore termina, tuttavia, tutti i suoi figli hanno il assegnato come nuovo genitore al processo di inizializzazione. Pertanto, i bambini hanno ancora un genitore per raccogliere le statistiche sullo stato e sull'esecuzione. (da "concetti di sistema operativo")

SOLUZIONE: uso ps-tree per ottenere tutti i processi che un child_process forse iniziato, in modo che essi

exec() in realtà funziona così:

function exec (cmd, cb) { 
    spawn('sh', ['-c', cmd]); 
    ... 
} 

Quindi controlla l'esempio e adattalo alle tue esigenze

var cp = require('child_process'), 
psTree = require('ps-tree'); 

var child = cp.exec("node -e 'while (true);'", function() { /*...*/ }); 

psTree(child.pid, function (err, children) { 
    cp.spawn('kill', ['-9'].concat(children.map(function (p) { return p.PID }))); 
});