2016-03-17 44 views
7

Ho un'applicazione in Go che reindirizza lo STDIN e lo STDOUT dei binari e quindi li esegue. In poche parole che sto facendo:Golang: I processi figlio diventano Zombi

- create command object with the binary path (lets call the object command A) - create command object with the binary path (calling it command B) - set the stdout of command B to the stdin of Command A - start command A - start command B

ho notato ogni volta che il processo per le uscite di comando B, mentre il comando A è in funzione, diventa un processo zombie nella tabella dei processi.

Ecco un esempio:

commandA := exec.Command("samplebin") 
commandB := exec.Command("sample2bin") 

cmdAStdin := commandA.StdinPipe() 

commandB.Stdout = cmdAStdin 

commandA.Start() 
commandB.Start() 

Perché commandB diventare uno Zombie, se esce mentre Commanda è ancora in esecuzione? Sto eseguendo Go 1.5 su Ubuntu 14.

risposta

11

Quando un processo termina, lo SEMPRE diventa uno zombie, indipendentemente da ciò che altri processi sono in esecuzione. Questo è solo il modo in cui la terminazione del processo funziona. Il processo rimarrà uno zombi fino a quando il genitore chiama lo wait per ottenere il suo stato di uscita, o indica che non è interessato ai bambini ignorando SIGCHLD (che potrebbe essere stato prima dell'uscita del bambino). Rimarrà uno zombi finché ciò non accadrà, per evitare che lo stato di uscita si perda.

Nel tuo esempio, sembrerebbe che il tuo processo (quello che crea i processi) sia il genitore, quindi sia A che B rimarranno come zombi finché il tuo processo non li raccoglierà.

Se un processo termina mentre ha ancora figli (in esecuzione o zombi), questi figli verranno riparati dal genitore del processo in uscita, che generalmente ignorerà lo stato di uscita (azzerando gli zombi).

+0

Quindi, SIGCHLD viene inviato dai processi figlio appena prima che diventino Zombi? Allora come si "ignora" SIGCHLD? Prendendo il segnale e facendo nulla? – AJPennster

+0

SIGCHLD viene inviato dal kernel quando un bambino fa parte di renderlo uno zombie. Se vuoi ignorare SIGCHLD e ottenere ancora zombi, imposta l'azione SIGCHLD su SIG_DFL (il valore predefinito) anziché su SIG_IGN - l'azione predefinita è non fare nulla, ma ottenere comunque zombi. –

+0

Non voglio gli zombi, voglio che i processi usciti siano ripuliti. Ho provato a impostare i segnali nell'applicazione principale per ignorare SIGCHLD e questo ha reso gli zombi quindi ho finito per chiamare Wait(). – AJPennster

2

D'accordo con la prima risposta che i processi in uscita diventano zombi finché il processo non viene aspettato da un altro processo. Ecco come gestisco le cose in corso.

package main 

import (
    "bytes" 
    "io" 
    "os" 
    "os/exec" 
) 

func main() { 
    c1 := exec.Command("samplebin") 
    c2 := exec.Command("sample2bin") 

    r, w := io.Pipe() 
    c1.Stdout = w 
    c2.Stdin = r 

    var b2 bytes.Buffer 
    c2.Stdout = &b2 

    // Writing without a reader will deadlock so write in a goroutine 
    go func() { 
     // Close the writer or the pipe will not be closed for c2 
     defer w.Close() 
     defer c1.Wait() 
     c1.Start() 
    }() 
    defer c2.Wait() 
    c2.Start() 
    io.Copy(os.Stdout, &b2) 
}