From 90004b9032d1b631f64aef5f7ee871e56ced39fe Mon Sep 17 00:00:00 2001 From: Min RK Date: Sat, 12 Aug 2017 16:11:09 +0200 Subject: [PATCH] schedule IOLoop.stop on the main thread loop.stop() will not be safe from a thread in tornado 5 There has never been a guarantee to this effect, but it has happened to be true so far. The result is that the stop event will not fire until the next loop iteration (e.g. triggered by an HTTP request). Using add_callback ensures that the main thread wakes and handles the stop event. cf tornado#2119 --- notebook/notebookapp.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/notebook/notebookapp.py b/notebook/notebookapp.py index 97599f276..6607bf940 100755 --- a/notebook/notebookapp.py +++ b/notebook/notebookapp.py @@ -1277,7 +1277,9 @@ class NotebookApp(JupyterApp): line = sys.stdin.readline() if line.lower().startswith(yes) and no not in line.lower(): self.log.critical(_("Shutdown confirmed")) - ioloop.IOLoop.current().stop() + # schedule stop on the main thread, + # since this might be called from a signal handler + self.io_loop.add_callback(self.io_loop.stop) return else: print(_("No answer for 5s:"), end=' ') @@ -1286,11 +1288,11 @@ class NotebookApp(JupyterApp): # set it back to original SIGINT handler # use IOLoop.add_callback because signal.signal must be called # from main thread - ioloop.IOLoop.current().add_callback(self._restore_sigint_handler) + self.io_loop.add_callback(self._restore_sigint_handler) def _signal_stop(self, sig, frame): self.log.critical(_("received signal %s, stopping"), sig) - ioloop.IOLoop.current().stop() + self.io_loop.add_callback(self.io_loop.stop) def _signal_info(self, sig, frame): print(self.notebook_info())