Python

[python] subprocess.run()과 Popen()의 timeout

thxxyj 2023. 4. 12. 14:39
728x90

 

[문제] subprocess.TimeoutExpired 에러가 발생한 경우, subprocess.run() 에서는 child process를 삭제할 수 없음

[해결]  subprocess.Popen()으로 converting 했다.

 

방법 1. proc.kill()로 프로세스 종료

https://docs.python.org/3.9/library/subprocess.html

The child process is not killed if the timeout expires, so in order to cleanup properly a well-behaved application should kill the child process and finish communication:

proc = subprocess.Popen(cmd, ...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    print('timeout expired')
    proc.kill()
    outs, errs = proc.communicate()

그런데 어떤 경우에는 TimeoutExpired에서 proc.kill()을 해도 proc.communicate() 으로 넘어가지 않고 그대로 물려있다.

 

+추가) proc.terminate() -> proc.kill() 시 원하는대로 프로세스 종료되고 proc.communicate() 실행됨

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

 

 

방법 2. os.killpg(os.getpgid(proc.pid), signal.SIGTERM) 로 프로세스 종료

참고 https://alexandra-zaharia.github.io/posts/kill-subprocess-and-its-children-on-timeout-python/

import os
import signal
import subprocess

try:
    proc = subprocess.Popen(cmd, ..., start_new_session=True)
    outs, errs = proc.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
    print('timeout expired!!!')
    os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
    outs, errs = proc.communicate()

이 경우에는 TimeoutExpired에서 프로세스 signal.SIGTERM 후에 proc.communicate() 으로 넘어가고 다음으로 진행되었다.

 

 

+ 추가)

위 코드를 통해 child process를 종료한 뒤, ps -ef로 확인했을 때 아래와 같이 <defunct> (좀비프로세스)가 남는 경우가 있었으나, 해당 프로세스의 ppid를 kill 하지 않아도 문제 없이 넘어갔다.

* how to get ppid? --> ppid = psutil.Process(os.getpgid(proc.pid)).ppid())

UID          PID    PPID  C STIME TTY          TIME CMD
jenkins     1550    1464 99 15:36 ?        00:00:04 python3 -u test.py
jenkins     1550    1464 99 15:36 ?        00:00:05 [python3]     # kill 후 -> 1550 프로세스 남아있음
jenkins     1550    1464 83 15:36 ?        00:00:05 [python3] <defunct>   # kill 후 -> 1550 프로세스 남아있음

 

 

728x90