Python 2 does not process signals if TCPServer is running in a different thread

While playing with the standard library, I discovered a strange difference between python2 and python3. If I try to catch a signal in python2 while TCPServer is running in a different thread, the signal is not processed, but in python3 it does.

Here is a script that reproduces the problem

import signal
import threading
import sys 
if sys.version_info > (3,0):
    from socketserver import TCPServer, BaseRequestHandler
else:
    from SocketServer import TCPServer, BaseRequestHandler

def shutdown(signum, frame):
    print("Shutting down server thread")
    server.shutdown()

server = TCPServer(
    ('127.0.0.1', 7654),
    BaseRequestHandler
)
signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)
server_thread = threading.Thread(target=server.serve_forever)
print("Starting server thread")
server_thread.start()
print("Waiting for server thread to shut down")
server_thread.join()
print("Server thread terminated")

This is the output of python3:

Starting server thread
Waiting for server thread to shut down
^CShutting down server thread
Server thread terminated

And this is from python2:

Starting server thread
Waiting for server thread to shut down
^CKilled

"^ C" is the keyboard interrupt, and "Killed" is the sigkill that I sent to the process.

Why was the shutdown not called?

+5
source share
1 answer

It seems to me that thread.join () does some blocking and does not allow to catch a signal.

I tested the following code in Python 2.7 and it seems to work:

import time
import signal
import threading
import sys 
if sys.version_info > (3,0):
    from socketserver import TCPServer, BaseRequestHandler
else:
    from SocketServer import TCPServer, BaseRequestHandler

def shutdown(signum, frame):
    print("Shutting down server thread")
    server.running = False
    server.shutdown()

server = TCPServer(
    ('127.0.0.1', 7654),
    BaseRequestHandler
)
signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)
server_thread = threading.Thread(target=server.serve_forever)
print("Starting server thread")
server_thread.start()
server.running = True
print("Waiting for server thread to shut down")

while server.running:
    time.sleep(1)

server_thread.join()
print("Server thread terminated")
+4
source

All Articles