Python: как предотвратить получение подпроцессов CTRL-C / Control-C / SIGINT

в настоящее время я работаю над оболочкой для выделенного сервера, работающего в оболочке. Оболочка порождает серверный процесс через подпроцесс и наблюдает и реагирует на его вывод.

выделенному серверу должна быть явно дана команда для изящного завершения работы. Таким образом, CTRL-C не должен достигать серверного процесса.

Если я захватываю исключение KeyboardInterrupt или перезаписываю обработчик SIGINT в python, серверный процесс по-прежнему получает CTRL-C и останавливается немедленно.

Итак, мой вопрос: Как предотвратить получение подпроцессов CTRL-C / Control-C / SIGINT?

4 ответов


кто-то в IRC-канале #python (Freenode) помог мне, указав preexec_fn


объединение некоторых других ответов, которые сделают трюк - никакой сигнал, отправленный в главное приложение, не будет перенаправлен в подпроцесс.

import os
from subprocess import Popen

def preexec(): # Don't forward signals.
    os.setpgrp()

Popen('whatever', preexec_fn = preexec)

попробуйте установить SIGINT на игнорировать перед созданием подпроцесса (сбросьте его до поведения по умолчанию после).

Если это не сработает, вам нужно будет прочитать Контрольная работа и узнать, как поместить процесс в свою собственную фоновую группу процессов, так что ^C даже не заставляет ядро посылать ему сигнал в первую очередь. (Возможно, невозможно в Python без написания помощников C.)

см. также этот старый вопрос.


вы можете сделать что-то вроде этого, чтобы заставить его работать в windows и unix:

import subprocess
import sys

def pre_exec():
    # To ignore CTRL+C signal in the new process
    signal.signal(signal.SIGINT, signal.SIG_IGN)

if sys.platform.startswith('win'):
    #https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
    #CREATE_NEW_PROCESS_GROUP=0x00000200 -> If this flag is specified, CTRL+C signals will be disabled
    my_sub_process=subprocess.Popen(["executable"], creationflags=0x00000200)
else:
    my_sub_process=subprocess.Popen(["executable"], preexec_fn = pre_exec)