#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