Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2 does not handle signals if TCPServer is running in another thread

While playing with standard library i've found 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 does not get handled, 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 from 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 a keyboard interrupt and "Killed" is sigkill that i sent to a process.

Why shutdown was not called?

like image 320
Blin Avatar asked Oct 07 '22 15:10

Blin


1 Answers

For me it seems thread.join() makes some lock and prevents from catching the signal.

I've 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")
like image 116
Tisho Avatar answered Oct 12 '22 12:10

Tisho