반응형

출처 : https://stackoverflow.com/questions/19461744/how-to-make-parent-wait-for-all-child-processes-to-finish

부모가 모든 자식 프로세스가 끝날 때까지 기다리는 방법?

저는 fork를 계속하기 전에 부모가 모든 자식 프로세스가 끝날 때까지 기다리는 방법을 밝힐 수 있기를 바랍니다. 실행하려는 정리 코드가 있지만 이러한 일이 발생하기 전에 자식 프로세스가 반환되어야 합니다.

for (int id=0; id<n; id++) {
  if (fork()==0) {
    // 자식
    exit(0);
  } else {
    // 부모
    ...
  }
  ...
}

3개의 답변 중 1개의 답변

pid_t child_pid, wpid; 
int status = 0; 

// 아버지 코드 (자식 프로세스가 시작하기 전에) 

for (int id=0; id<n; id++) { 
    if ((child_pid = fork()) == 0) { 
        // 자식 코드
        exit(0); 
    } 
} 

while ((wpid = wait(&status)) > 0); // 이 방법으로 아버지는 모든 자식 프로세스를 기다립니다.

// 아버지 코드 (모든 자식 프로세스가 끝난 후에)

wait 는 하위 프로세스가 종료 될 때까지 대기하고 해당 하위 프로세스의 pid를 리턴합니다. 오류가 발생하면 (예 : 하위 프로세스가 없는 경우) -1이 반환됩니다. 따라서 기본적으로 코드는 wait(대기) 오류가 끝날 때까지 자식 프로세스가 완료될 때까지 계속 기다렸다가 모두 완료되었음을 알 수 있습니다.

반응형
반응형

출처 : https://stackoverflow.com/questions/19447603/how-to-kill-a-python-child-process-created-with-subprocess-check-output-when-t

부모 프로세스가 죽을 때 subprocess.check_output()로 생성된 Python 자식 프로세스를 죽이는 방법?

저는 다음처럼 subprocess.check_output()을 사용하는 자식 프로세스를 생성하는 python script를 리눅스 머신에서 실행하려고 합니다.

subprocess.check_output(["ls", "-l"], stderr=subprocess.STDOUT)

문제는 부모 프로세스가 죽었을 때 조차 자식 프로세스가 실행중이라는 것입니다. 부모 프로세스가 죽었을 때 자식 프로세스도 함께 죽일 수 있는 방법이 있습니까?


5개의 답변 중 2개의 답변

당신의 문제는 subprocess.check_output을 사용하는 것입니다. - 당신은 맞게 작성 했습니다만 check_ouput 인터페이스로는 자식 프로세스의 PID를 얻을 수 없습니다. 대신에 Popen을 사용하세요.

proc = subprocess.Popen(["ls", "-l"], stdout=PIPE, stderr=PIPE)

# 여기에서 자식 프로세스의 PID를 얻을 수 있습니다.
global child_pid
child_pid = proc.pid

# 여기서 자식 프로세스가 완료될 때까지 기다릴 수 있습니다.
(output, error) = proc.communicate()

if error:
    print "error:", error

print "output:", output

종료할 때 자식 프로세스를 죽이는 것을 분명하게 만드세요.

import os
import signal
def kill_child():
    if child_pid is None:
        pass
    else:
        os.kill(child_pid, signal.SIGTERM)

import atexit
atexit.register(kill_child)

당신은 두 개의 방법으로 이를 할 수 있습니다. 그들은 check_output 대신에 Popen을 사용해야 합니다. 첫 번째는 다음처럼 try..finally 를 사용하는 더 간단한 방법입니다.

from contextlib import contextmanager

@contextmanager
def run_and_terminate_process(*args, **kwargs):
try:
    p = subprocess.Popen(*args, **kwargs)
    yield p        
finally:
    p.terminate() # sigterm을 보내고, ...
    p.kill()      # sigkill을 보냅니다.

def main():
    with run_and_terminate_process(args) as running_proc:
        # running_proc.stdout.readline() 처럼 당신의 코드를 여기에 작성합니다.

이는 sigint(키보드 인터럽트)와 sigterm을 잡아내지만, sigkill(-9로 kill 스트립트 실행)을 잡아내지 못합니다.

다른 방법은 좀 더 복잡한데 ctypes의 rctl PR_SET_PDEATHSIG을 사용하는 것입니다. 시스템은 자식에게 시그널을 보낼것이고 부모는 어떤 이유(심지어 sigkill)로든 종료합니다.

import signal
import ctypes
libc = ctypes.CDLL("libc.so.6")
def set_pdeathsig(sig = signal.SIGTERM):
    def callable():
        return libc.prctl(1, sig)
    return callable
p = subprocess.Popen(args, preexec_fn = set_pdeathsig(signal.SIGTERM))
반응형

+ Recent posts