Mientras jugaba con la biblioteca estándar, encontré una extraña diferencia entre python2 y python3. Si trato de captar una señal en python2 mientras TCPServer se está ejecutando en un hilo diferente, la señal no se maneja, pero en python3 sí.

Aquí hay un guión que reproduce el problema.

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")

Esta es la salida de python3:

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

Y esto es de python2:

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

"^ C" es una interrupción del teclado y "Killed" es sigkill que envié a un proceso.

¿Por qué no se llamó al cierre?

5
Blin 7 jun. 2012 a las 00:58
¿Cómo se envía la señal SIG_INT al proceso?
 – 
Tisho
7 jun. 2012 a las 01:22
En los sistemas POSIX, Control-C hace que el programa activo reciba una señal SIGINT. wiki
 – 
Blin
7 jun. 2012 a las 01:42
Ok, al menos sabemos que la señal SIGKILL funciona. Si vincula SIGKILL para que se apague, ¿funcionará?
 – 
Tisho
7 jun. 2012 a las 01:56
... al menos esta comprobación mostrará dónde podría estar el problema.
 – 
Tisho
7 jun. 2012 a las 02:25
@Tisho: excepto, por supuesto, que la señal SIGKILL no puede ser captada.
 – 
mhawke
7 jun. 2012 a las 04:18

1 respuesta

La mejor respuesta

Para mí, parece que thread.join () bloquea un poco y evita que capte la señal.

Probé el siguiente código en Python 2.7 y parece funcionar:

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
Tisho 7 jun. 2012 a las 11:58