Убийство дочернего процесса, когда родительский сбой в python

Я пытаюсь написать программу python для тестирования сервера, написанного на C. Программа python запускает скомпилированный сервер с помощью модуля subprocess:

pid = subprocess.Popen(args.server_file_path).pid

Это прекрасно работает, однако, если программа python неожиданно завершается из-за ошибки, процесс порождения остается включенным. Мне нужен способ убедиться, что если программа python неожиданно завершится, серверный процесс также будет убит.

Дополнительная информация:

  • Только операционные системы Linux или OSX
  • Код сервера не может быть изменен каким-либо образом

Ответ 1

Я бы atexit.register функцию для завершения процесса:

import atexit
process = subprocess.Popen(args.server_file_path)
atexit.register(process.terminate)
pid = process.pid

Или, может быть:

import atexit
process = subprocess.Popen(args.server_file_path)
@atexit.register
def kill_process():
    try:
        process.terminate()
    except OSError:
        pass #ignore the error.  The OSError doesn't seem to be documented(?)
             #as such, it *might* be better to process.poll() and check for 
             #`None` (meaning the process is still running), but that 
             #introduces a race condition.  I'm not sure which is better,
             #hopefully someone that knows more about this than I do can 
             #comment.

pid = process.pid

Обратите внимание, что это не поможет вам, если вы делаете что-то неприятное, чтобы заставить python умереть не изящным способом (например, через os._exit или вы вызываете SegmentationFault или BusError)