KeyboardInterrupt and threading

Ivan Nestlerode q2n8byu02 at sneakemail.com
Tue Jan 6 21:44:07 EST 2004


Michael Hudson <mwh at python.net> wrote in message news:<m3fzeu73k3.fsf at pc150.maths.bris.ac.uk>...
> On debian, the signal module certainly should be available, and the
> KeyboardInterrupt exception should go to the main thread.  Or at
> least, that's what I thought.  You're definitely seeing it being
> delivered to an arbitrary thread?
> 
> Cheers,
> mwh

After a closer look, I am not seeing KeyboardInterrupt being delivered
to non-main threads. What I am seeing is that Ctrl-C does not work at
all when non-main threads are CPU intensive. I had previously jumped
to the conclusion that because Ctrl-C didn't work and because the
non-main thread was sloppy ("except:"), that Ctrl-C wasn't working
because KeyboardInterrupt was going to the sub-thread. That was an
incorrect conclusion.

So I guess the entire problem can be restated as:
How do I make Ctrl-C work properly when the non-main thread is busier
than the main thread?

The short program at the end of this post demonstrates the problem
with Ctrl-C and busy non-main threads. The idea behind this script is
that the main thread launches a busy sub-thread. Ctrl-C is supposed to
be caught in the main thread, stopping both threads, and ending the
program (with some printouts). As written, the program does not
respond to Ctrl-C even if I hold it down continuously. If you
uncomment the print statement in the main thread, all of the sudden it
starts to work. Why?

I think it has something to do with the main thread needing some
larger amount of CPU to detect the signal and the KeyboardInterrupt. I
think this is a bug though (I shouldn't have to put hacks into the
main thread to get this to work).

Any thoughts?

Thanks,
-Ivan


#!/usr/bin/python

from threading import Event, Thread
from time import sleep

class CpuHogThread(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.counter = 0
        self.stopEvent = Event()

    def join(self):
        self.stopEvent.set()
        Thread.join(self)

    def run(self):
        try:
            while not self.stopEvent.isSet():
                self.counter += 1
        except KeyboardInterrupt:
            print 'CPU hog subthread caught KeyboardInterrupt'

if __name__ == '__main__':
    t = CpuHogThread()
    t.start()
    print 'CPU hog subthread spawned'
    try:
        while True:
            sleep(2)
            # without the next print, Ctrl-C is completely ignored
            #print 'still sleeping'
    except KeyboardInterrupt:
        print 'main thread caught KeyboardInterrupt'
        t.join()
        print 'CPU hog subthread joined at counter %d' % t.counter



More information about the Python-list mailing list