Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

The dedicated server must be explicitly given a command to shut down gracefully. Thus, CTRL-C must not reach the server process.

If I capture the KeyboardInterrupt exception or overwrite the SIGINT-handler in python, the server process still receives the CTRL-C and stops immediately.

So my question is: How to prevent subprocesses from receiving CTRL-C / Control-C / SIGINT?

like image 622
robert Avatar asked Feb 18 '11 19:02

robert


People also ask

Does control c Send sigint?

The CTRL + C and CTRL + BREAK key combinations receive special handling by console processes. By default, when a console window has the keyboard focus, CTRL + C or CTRL + BREAK is treated as a signal (SIGINT or SIGBREAK) and not as keyboard input.

What is sigint Ctrl C?

The CTRL + C is one signal in C or C++. So we can catch by signal catching technique. For this signal, the code is SIGINT (Signal for Interrupt). Here the signal is caught by signal() function. Then one callback address is passed to call function after getting the signal.

How does Python handle Ctrl C?

You can handle CTRL + C by catching the KeyboardInterrupt exception. You can implement any clean-up code in the exception handler.


1 Answers

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.

like image 142
robert Avatar answered Oct 01 '22 19:10

robert