Python: How to prevent subprocesses from receiving CTRL-C / Control-C / SIGINT

前端 未结 5 798
有刺的猬
有刺的猬 2020-12-13 00:26

I am currently working on a wrapper for a dedicated server running in the shell. The wrapper spawns the server process via subprocess and observes and reacts to its output.<

相关标签:
5条回答
  • 2020-12-13 00:30

    After an hour of various attempts, this works for me:

    process = subprocess.Popen(["someprocess"], creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP)
    

    It's solution for windows.

    0 讨论(0)
  • 2020-12-13 00:36

    Try setting SIGINT to be ignored before spawning the subprocess (reset it to default behavior afterward).

    If that doesn't work, you'll need to read up on job control and learn how to put a process in its own background process group, so that ^C doesn't even cause the kernel to send the signal to it in the first place. (May not be possible in Python without writing C helpers.)

    See also this older question.

    0 讨论(0)
  • 2020-12-13 00:49

    you can do something like this to make it work in windows and 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)
    
    0 讨论(0)
  • 2020-12-13 00:51

    Somebody in the #python IRC-Channel (Freenode) helped me by pointing out the preexec_fn parameter of subprocess.Popen(...):

    If preexec_fn is set to a callable object, this object will be called in the child process just before the child is executed. (Unix only)

    Thus, the following code solves the problem (UNIX only):

    import subprocess
    import signal
    
    def preexec_function():
        # Ignore the SIGINT signal by setting the handler to the standard
        # signal handler SIG_IGN.
        signal.signal(signal.SIGINT, signal.SIG_IGN)
    
    my_process = subprocess.Popen(
        ["my_executable"],
        preexec_fn = preexec_function
    )
    

    Note: The signal is actually not prevented from reaching the subprocess. Instead, the preexec_fn above overwrites the signal's default handler so that the signal is ignored. Thus, this solution may not work if the subprocess overwrites the SIGINT handler again.

    Another note: This solution works for all sorts of subprocesses, i.e. it is not restricted to subprocesses written in Python, too. For example the dedicated server I am writing my wrapper for is in fact written in Java.

    0 讨论(0)
  • 2020-12-13 00:56

    Combining some of other answers that will do the trick - no signal sent to main app will be forwarded to the subprocess.

    import os
    from subprocess import Popen
    
    def preexec(): # Don't forward signals.
        os.setpgrp()
    
    Popen('whatever', preexec_fn = preexec)
    
    0 讨论(0)
提交回复
热议问题