#8975 NORM Not Tri: thread.interrupt_main() unreliability
Zarro Boogs per Child
bugtracker at laptop.org
Tue Nov 11 16:11:27 EST 2008
#8975: thread.interrupt_main() unreliability
--------------------------+-------------------------------------------------
Reporter: ssb22 | Owner:
Type: defect | Status: new
Priority: normal | Milestone: Not Triaged
Component: not assigned | Version: not specified
Keywords: | Next_action: never set
Verified: 0 | Deployment_affected:
Blockedby: | Blocking:
--------------------------+-------------------------------------------------
This ticket is of limited use because I have been unable to ascertain
under exactly what circumstances this bug arises. But I'm filing it
anyway because its main contribution is to say that os.kill(os.getpid(),
signal.SIGINT) is likely to be more reliable than thread.interrupt_main()
in Python code, especially if Tkinter is introduced in future for ease of
GUI development.
The story: I was trying to port Gradint to the OLPC. It uses Tkinter so I
installed that (I'm using a B4 build 767 firmware Q2E18 without network
connectivity and I went to
http://ftp.linux.org.uk/pub/distributions/fedora/linux/updates/9/i386.newkey/
and downloaded tcl-8.5.2-2.fc9.i386.rpm tix-8.4.2-6.fc9.i386.rpm
tk-8.5.2-1.fc9.i386.rpm tkinter-2.5.1-26.fc9.i386.rpm then transferred to
the XO and rpm -i'd them). Gradint runs its Tkinter GUI in a separate
thread with commands running in the main thread. Both threads communicate
with each other using poll loops, and anything that's going to take a long
time is done in the main thread so that the GUI remains responsive. When
the user presses the Quit button, thread.interrupt_main() is called and
the main thread handles the resulting KeyboardInterrupt, and if the
program really is in a state where it can quit then it tells the GUI to
exit and then exits itself. Well when I rigged up a 20-line test program
with this architecture, the Quit button worked instantly every time. But
in Gradint, it didn't take effect until you pressed another button after
it. I tried all kinds of things, but could not reproduce this in the
simple test program. I did find some ways of preventing it from happening
in Gradint but they were rather strange (like queuing a "goodbye" message
box to be displayed by the GUI thread when it nexts poll()s - but
displaying a message box in the "quit" callback will NOT have the same
effect). It wasn't at all obvious what was going on.
But what did work every time was os.kill(os.getpid(), signal.SIGINT) so I
suggest using that instead of thread.interrupt_main(). It might even be a
good idea to add to some site-startup script something like
import thread,os,signal
def interrupt_main(): os.kill(os.getpid(), signal.SIGINT)
thread.interrupt_main = interrupt_main()
i.e. override thread.interrupt_main to the new behaviour.
--
Ticket URL: <http://dev.laptop.org/ticket/8975>
One Laptop Per Child <http://laptop.org/>
OLPC bug tracking system
More information about the Bugs
mailing list