[pyar] Threads + señales.

Marcelo Fernandez marcelo.fidel.fernandez en gmail.com
Mie Sep 8 23:59:02 ART 2010


2010/9/8 Lucas Liendo <mindmaster en gmail.com>:
> Buenas a todos !. Estuve probando algunas cosas con señales, en particular
> como se comportaban las señales cuando se ejecuta mas de un hilo. Les pego
> un pequeño codigo de prueba el cual levanta 2 threads y establece un signal
> handler para SIGUSR1. Lo curioso es que al enviar la señal el programa
> termina pero el handler no es invocado. Estableciendo el handler al comienzo
> de programa (es decir, justo luego del if __name___) es como no haberlo
> definido. ¿Alguien ya tuvo este incoveniente o alguno similar?
>

Hola Lucas,

Estuve jugando con tu ejemplo, y después de leer este segmento de la
doc estándar de Python [1] y este artículo [2] (en particular ésta
parte [3]), llegué a darme cuenta de dónde estaba el problema: dado
que los hilos secundarios no reciben señales, para que la señal se
despache, el main thread debe estar haciendo algo. Mirá este ejemplo
readaptado del tuyo:

import os
import signal
import time
from threading import Thread

def sigTermHandler(signum, frame):
    print "Terminating..."
    thread1.stop()
    thread2.stop()

class testThread(Thread):
    def __init__(self, msg):
        Thread.__init__(self)
        self.msg = msg
        self.terminate = False

    def run(self):
        while not self.terminate:
            print self.msg
            time.sleep(1)

    def stop(self):
        self.terminate = True

if __name__ == "__main__":
    print 'My PID is:', os.getpid()
    signal.signal(signal.SIGUSR1, sigTermHandler)

    thread1 = testThread('First thread.')
    thread2 = testThread('Second thread.')
    thread1.start()
    thread2.start()

    # The main thread *MUST* be doing something to catch and dispatch
the signal handler
    while not thread1.terminate or not thread2.terminate:
        print "Main process."
        time.sleep(1)

Si el bloque while del main process lo comentás, la señal nunca se
procesa, porque el intérprete de Python sólo tiene hilos secundarios
para correr, y como bien dice la documentación, sólo un hilo primario
recibe/despacha señales.

Una observación más con el ejemplo que mandaste: No te olvides que
join() es bloqueante, mucho más si tu hilo está en un While True. :-P

Espero que te sirva.

[1] http://docs.python.org/library/signal.html
"Some care must be taken if both signals and threads are used in the
same program. The fundamental thing to remember in using signals and
threads simultaneously is: always perform signal() operations in the
main thread of execution. Any thread can perform an alarm(),
getsignal(), pause(), setitimer() or getitimer(); only the main thread
can set a new signal handler, and the main thread will be the only one
to receive signals (this is enforced by the Python signal module, even
if the underlying thread implementation supports sending signals to
individual threads). This means that signals can’t be used as a means
of inter-thread communication. Use locks instead."

[2] http://www.doughellmann.com/PyMOTW/signal/
[3] http://www.doughellmann.com/PyMOTW/signal/#signals-and-threads

Saludos
-- 
Marcelo F. Fernández
Buenos Aires, Argentina
Licenciado en Sistemas - CCNA

E-Mail: marcelo.fidel.fernandez en gmail.com
Blog: http://blog.marcelofernandez.info
Twitter: http://twitter.com/fidelfernandez



More information about the pyar mailing list