Home > Back-end >  Ctrl c not stopping a Thread in Windows python3.7
Ctrl c not stopping a Thread in Windows python3.7

Time:11-15

I'm trying this simple thread with a while loop inside. When I'm inside the while loop, Ctrl C has no effect in stopping my program. Once I go do something else after the while loop, the script stops as intended. What can I do so my script can be gracefully killed both while being in the while loop and after? (Edit: This seems to be a problem exclusive to Windows, iOS and Ubuntu seem to do what I want)

import time, threading


class MainClass(threading.Thread):

    def __init__(self):
        super().__init__()

    def run(self):
        while True:
            time.sleep(1)
            print("Looping")


# Script entry point
if __name__ == '__main__':

    a = MainClass()
    a.daemon = True
    a.start()
    a.join()

CodePudding user response:

This is a known issue, explained in Issue 35935.

A way to solve it is to use an event, which is passed into the thread class, which waits for the SIGINT to be triggered. As I understand, a way to overcome the fact that the main thread is blocking the event signal is to revert to the default kernel behaviour of SIGINT using signal.signal(signal.SIGINT, signal.SIG_DFL), (solution pointed out by the issue OP), and the meaning of SIG_DFL is explained f.e. here. As to why this has to be the case is beyond the scope of my knowledge.

This is by no means a perfect solution, but works on Windows using Python 3.8 .

Implementation:

import time, threading
import signal


class MainClass(threading.Thread):

    def __init__(self,event):
        super().__init__()
        self.event = event

    def run(self):
        while not event.is_set():
            time.sleep(1)
            print("Looping")


# Script entry point
if __name__ == '__main__':
    try:
        event = threading.Event()
        a = MainClass(event)
        a.daemon=True
        a.start()
       
        signal.signal(signal.SIGINT, signal.SIG_DFL)

        event.wait()
    except KeyboardInterrupt:
        event.set()
        sys.exit(1)
  • Related