5

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?

ThiefMaster
  • 285,213
  • 77
  • 557
  • 610
Blin
  • 678
  • 9
  • 18

1 Answers1

4

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")
Tisho
  • 7,474
  • 5
  • 40
  • 52