##// END OF EJS Templates
MTInteractiveShell: implement "code received" event in runsource & runcode to prevent hanging indefinitely when the mainloop is dead (typical with -gthread) if you close the window
Ville M. Vainio -
Show More
@@ -22,7 +22,7 b" name = 'ipython'"
22 # because bdist_rpm does not accept dashes (an RPM) convention, and
22 # because bdist_rpm does not accept dashes (an RPM) convention, and
23 # bdist_deb does not accept underscores (a Debian convention).
23 # bdist_deb does not accept underscores (a Debian convention).
24
24
25 revision = '46'
25 revision = '52'
26
26
27 version = '0.8.3.bzr.r' + revision
27 version = '0.8.3.bzr.r' + revision
28
28
@@ -372,6 +372,7 b' class MTInteractiveShell(InteractiveShell):'
372 self.on_kill = on_kill
372 self.on_kill = on_kill
373 # thread identity of the "worker thread" (that may execute code directly)
373 # thread identity of the "worker thread" (that may execute code directly)
374 self.worker_ident = None
374 self.worker_ident = None
375
375 def runsource(self, source, filename="<input>", symbol="single"):
376 def runsource(self, source, filename="<input>", symbol="single"):
376 """Compile and run some source in the interpreter.
377 """Compile and run some source in the interpreter.
377
378
@@ -411,9 +412,18 b' class MTInteractiveShell(InteractiveShell):'
411 # Case 3
412 # Case 3
412 # Store code in queue, so the execution thread can handle it.
413 # Store code in queue, so the execution thread can handle it.
413
414
414 ev = threading.Event()
415 completed_ev, received_ev = threading.Event(), threading.Event()
415 self.code_queue.put((code,ev))
416
416 ev.wait()
417 self.code_queue.put((code,completed_ev, received_ev))
418 # first make sure the message was received, with timeout
419 received_ev.wait(5)
420 if not received_ev.isSet():
421 # the mainloop is dead, start executing code directly
422 print "Warning: Timeout for mainloop thread exceeded"
423 print "switching to nonthreaded mode (until mainloop wakes up again)"
424 self.worker_ident = None
425 else:
426 completed_ev.wait()
417 return False
427 return False
418
428
419 def runcode(self):
429 def runcode(self):
@@ -450,9 +460,11 b' class MTInteractiveShell(InteractiveShell):'
450 code_to_run = None
460 code_to_run = None
451 while 1:
461 while 1:
452 try:
462 try:
453 code_to_run, event = self.code_queue.get_nowait()
463 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
454 except Queue.Empty:
464 except Queue.Empty:
455 break
465 break
466 received_ev.set()
467
456 # Exceptions need to be raised differently depending on which
468 # Exceptions need to be raised differently depending on which
457 # thread is active. This convoluted try/except is only there to
469 # thread is active. This convoluted try/except is only there to
458 # protect against asynchronous exceptions, to ensure that a KBINT
470 # protect against asynchronous exceptions, to ensure that a KBINT
@@ -466,13 +478,14 b' class MTInteractiveShell(InteractiveShell):'
466 except KeyboardInterrupt:
478 except KeyboardInterrupt:
467 print "Keyboard interrupted in mainloop"
479 print "Keyboard interrupted in mainloop"
468 while not self.code_queue.empty():
480 while not self.code_queue.empty():
469 code, ev = self.code_queue.get_nowait()
481 code, ev1,ev2 = self.code_queue.get_nowait()
470 ev.set()
482 ev1.set()
483 ev2.set()
471 break
484 break
472 finally:
485 finally:
473 CODE_RUN = False
486 CODE_RUN = False
474 # allow runsource() return from wait
487 # allow runsource() return from wait
475 event.set()
488 completed_ev.set()
476
489
477
490
478 # This MUST return true for gtk threading to work
491 # This MUST return true for gtk threading to work
General Comments 0
You need to be logged in to leave comments. Login now