2016-03-17 2 views
7

У меня есть приложение в Go, которое перенаправляет STDIN и STDOUT из двоичных файлов, а затем запускает их. В двух словах я делаю:Golang: Child Processes становятся зомби

- 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

я заметил, когда процесс выходит команда B, а команда А работает, он становится процессом зомби в таблице процессов.

Вот пример:

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

cmdAStdin := commandA.StdinPipe() 

commandB.Stdout = cmdAStdin 

commandA.Start() 
commandB.Start() 

Почему commandB стать зомби, если он выходит во время commandA все еще работает? Я бегу Go 1.5 на Ubuntu 14.

ответ

11

Когда процесс завершается, он ALWAYS становится зомби, независимо от того, какие другие процессы запущены. Это просто способ завершения процесса. Этот процесс останется зомби до тех пор, пока его родительский вызов не вызовет wait, чтобы получить его статус выхода, или указывает, что он не интересуется детьми, игнорируя SIGCHLD (который, возможно, был до выхода ребенка). Он останется зомбиком до тех пор, пока это не произойдет, чтобы статус выхода не потерялся.

В вашем примере, кажется, что ваш процесс (тот, кто создает процессы) является родителем, поэтому оба и А будут оставаться зомби, пока ваш процесс их не соберет.

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

+0

Итак, SIGCHLD отправляется дочерними процессами прямо перед тем, как стать зомби? Тогда как «игнорировать» SIGCHLD? Улавливая сигнал и ничего не делая? – AJPennster

+0

SIGCHLD отправляется ядром, когда ребенок является частью зомби. Если вы хотите игнорировать SIGCHLD и все еще получать зомби, установите действие SIGCHLD на SIG_DFL (по умолчанию), а не на SIG_IGN - действие по умолчанию - ничего не делать, но все равно получить зомби. –

+0

Я не хочу зомби, я хочу, чтобы очищенные процессы были очищены. Я попытался настроить сигналы в главном приложении, чтобы игнорировать SIGCHLD и что все еще сделал зомби, поэтому я в конечном итоге вызываю Wait(). – AJPennster

2

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

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) 
}