##// END OF EJS Templates
Allow recursive execution of IPython code in MTInteractiveShell.runsource by checking if we are already in worker thread, and execute code directly if we are.
Ville M. Vainio -
Show More
@@ -375,7 +375,8 b' class MTInteractiveShell(InteractiveShell):'
375 if not callable(t):
375 if not callable(t):
376 raise TypeError,'on_kill must be a list of callables'
376 raise TypeError,'on_kill must be a list of callables'
377 self.on_kill = on_kill
377 self.on_kill = on_kill
378
378 # thread identity of the "worker thread" (that may execute code directly)
379 self.worker_ident = None
379 def runsource(self, source, filename="<input>", symbol="single"):
380 def runsource(self, source, filename="<input>", symbol="single"):
380 """Compile and run some source in the interpreter.
381 """Compile and run some source in the interpreter.
381
382
@@ -406,7 +407,14 b' class MTInteractiveShell(InteractiveShell):'
406 # Note that with macros and other applications, we MAY re-enter this
407 # Note that with macros and other applications, we MAY re-enter this
407 # section, so we have to acquire the lock with non-blocking semantics,
408 # section, so we have to acquire the lock with non-blocking semantics,
408 # else we deadlock.
409 # else we deadlock.
409 got_lock = self.thread_ready.acquire()
410
411 # shortcut - if we are in worker thread, execute directly (to allow recursion)
412
413 if self.worker_ident == thread.get_ident():
414 InteractiveShell.runcode(self,code)
415 return
416
417 got_lock = self.thread_ready.acquire(blocking=False)
410 self.code_queue.put(code)
418 self.code_queue.put(code)
411 if got_lock:
419 if got_lock:
412 self.thread_ready.wait() # Wait until processed in timeout interval
420 self.thread_ready.wait() # Wait until processed in timeout interval
@@ -420,8 +428,8 b' class MTInteractiveShell(InteractiveShell):'
420 Multithreaded wrapper around IPython's runcode()."""
428 Multithreaded wrapper around IPython's runcode()."""
421
429
422 global CODE_RUN
430 global CODE_RUN
423
424 # lock thread-protected stuff
431 # lock thread-protected stuff
432 self.worker_ident = thread.get_ident()
425 got_lock = self.thread_ready.acquire()
433 got_lock = self.thread_ready.acquire()
426
434
427 if self._kill:
435 if self._kill:
@@ -448,7 +456,6 b' class MTInteractiveShell(InteractiveShell):'
448 code_to_run = self.code_queue.get_nowait()
456 code_to_run = self.code_queue.get_nowait()
449 except Queue.Empty:
457 except Queue.Empty:
450 break
458 break
451
452 # Exceptions need to be raised differently depending on which
459 # Exceptions need to be raised differently depending on which
453 # thread is active. This convoluted try/except is only there to
460 # thread is active. This convoluted try/except is only there to
454 # protect against asynchronous exceptions, to ensure that a KBINT
461 # protect against asynchronous exceptions, to ensure that a KBINT
General Comments 0
You need to be logged in to leave comments. Login now