I have a server that starts a subprocess, and I can manage to do a send_signal(SIGTERM)
which will kill the process. But not gracefully.
If I call my subprocess from shell (i.e. as a single process), the defined signal handler will kick in and exit gracefully.
server.py:
(so.. from another script I first call start_app()
, and later exit_app()
def start_app():
app = subprocess.Popen("python app.py")
def exit_app():
p = app.poll()
if p==None:
print("Subprocess is alive") # debug
app.send_signal(signal.SIGTERM)
app.py
def exit_signal_handler(signal, frame):
print("Terminate signal received")
app.exit()
if __name__ == '__main__':
app = QApplication(sys.argv)
signal.signal(signal.SIGTERM, exit_signal_handler)
signal.signal(signal.SIGINT, exit_signal_handler)
sys.exit(app.exec())
Again, if I call app.py from shell and send a SIGTERM
signal I get a trace Terminate signal received
and app closes.
But when app.py is started by server and I call exit_app
in server, I get a trace Subprocess is alive
(from server.py) and app is killed but the signal is not caught in app's signalhandler exit_signal_handler
EDIT:
It seems send_signal()
doesn't send a signal to the subprocess in the sense that subprocess catches the signal. It send`s a signal for an action to take place on the subprocess:
def send_signal(self, sig):
"""Send a signal to the process
"""
if sig == signal.SIGTERM:
self.terminate()
elif sig == signal.CTRL_C_EVENT:
os.kill(self.pid, signal.CTRL_C_EVENT)
elif sig == signal.CTRL_BREAK_EVENT:
os.kill(self.pid, signal.CTRL_BREAK_EVENT)
else:
raise ValueError("Unsupported signal: {}".format(sig))
This probably answers my question but I'll leave it open...
As you are using Windows, SIGTERM
handler is useless, more reference:
On Windows, the C runtime implements the six signals that are required by standard C: SIGINT, SIGABRT, SIGTERM, SIGSEGV, SIGILL, and SIGFPE.
SIGABRT and SIGTERM are implemented just for the current process.
But you could use signal.CTRL_BREAK_EVENT
as an alternative.
I.e. create a signal handler in app.py that handles SIGBREAK
, but send the CTRL_BREAK_EVENT
from the parent. Also, make sure to start your subprocess using creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
(otherwise it will kill the parent as well)
app = subprocess.Popen("python app.py", shell=True, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
time.sleep(1)
while 1:
p = app.poll()
if p is not None:
break
app.send_signal(signal.CTRL_BREAK_EVENT)
time.sleep(2)
app.py:
exit = False
def exit_signal_handler(signal, frame):
global exit
print("Terminate signal received")
exit = True
signal.signal(signal.SIGBREAK, exit_signal_handler)
while not exit:
pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With