Problem with threads in python.

1

I'm having some problems finishing some threads.

My program has a function runthreads ():

def runThreads():
    """
    Creates and runs threads.
    """

    t1 = threading.Thread(target=netstatCapture, name='netstatCapture')
    t2 = threading.Thread(target=tasklistCapture, name='tasklistCapture')
    t3 = threading.Thread(target=capture_from_wifi(), name='WiFiCapture')
    t4 = threading.Thread(target=capture_from_eth(), name='EthCapture')

    t1.daemon = True
    t1.start()
    t2.daemon = True
    t2.start()
    t3.daemon = True
    t3.start()
    t4.daemon = True
    t4.start()

This function is called by my main () function:

runThreads()

Then, I define main () as another thread, so that when I finish the threeads defined in runThreads () I do not finish the whole execution:

if __name__ == '__main__':
  main = threading.Thread(target=main, name='main_function')
  main.start()

The issue is that if I want to finish the execution, for example with ctrl + c, the threads defined in runThreads () do not end. How can I solve this?

Thanks !!!

PS: I'm using Python 2.7 and the threading library

    
asked by sooaran 18.03.2018 в 18:39
source

1 answer

0

In python 2.7 it is very problematic. The Ctrl-C sends a signal that is only sent to the main thread. You would have to install a signal handler ( signal() ) in that thread, capture it, and put some Boolean global variable that the other threads consult periodically to know that they should end. In Python 3 the signal is instead sent to all threads, and handled by default by the interpreter, so that pressing Ctlr-C twice, kills all threads.

In any case, even in Python3, the reasonable thing is not to kill a thread "without more", because it could be in the middle of some important operation, but to signal it to finish when it can, by means of some global variable.

Example

Here is an example that uses the technique described. I have implemented the functions netstatCapture and tasklistCapture as infinite loops that contain a time.sleep() . Your functions should also periodically call time.sleep() , since this is an interruptible function that will "wake up" before Ctrl-C. In any case, the loop is not infinite at all, but it looks up the global variable terminar to decide when to end.

This global variable is written from the appropriate signal handler, which is registered in the main program by signal.signal() .

Note that the main thread must be kept "alive", because in Python 2 it is the only one that will receive the Ctrl-C signal and if this thread were to die, the signal would be lost and the whole scheme would fail. To keep him alive, I put him in another waiting loop, like the other threads:

# coding: utf-8
import threading
import time
import signal

terminar = False

def procesarCtrlC(*args):
    """Manejador para la señal SIGINT"""
    global terminar
    terminar = True
    print("Detectado Ctrl-C con parametros {}".format(args))

def netstatCapture():
    print("Arrancando netstatCapture")
    while not terminar:
        time.sleep(2)
    print("Terminando netstatCapture")

def tasklistCapture():
    print("Arrancando tasklistCapture")
    while not terminar:
        time.sleep(2)
    print("Terminando tasklistCapture")


def runThreads():
    """
    Creates and runs threads.
    """

    t1 = threading.Thread(target=netstatCapture, name='netstatCapture')
    t2 = threading.Thread(target=tasklistCapture, name='tasklistCapture')

    t1.daemon = True
    t1.start()
    t2.daemon = True
    t2.start()

def main():
    print("Función principal")
    runThreads()
    print("Hios lanzados")
    while not terminar:
        time.sleep(4)
    print("Terminando main")

if __name__ == '__main__':
    # La siguiente línea "instala" el manejador de señal
    signal.signal(signal.SIGINT, procesarCtrlC)
    main = threading.Thread(target=main, name='main_function')
    main.start()
    while not terminar:
        time.sleep(3)

This solution will also work in Python 3, although in the case of Python 3 a Ctrl-C would also work without the need to program anything special, although that would kill the threads at any time, whereas the previous approach only ends the threads when they re-iterate in their while() and discover the termination condition, which is usually preferable because they have the opportunity to release resources, etc.

    
answered by 18.03.2018 в 18:52