diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 42f5125b0..8e64a212f 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -21,6 +21,17 @@ We strongly recommend that you upgrade pip to version 9+ of pip before upgrading Use ``pip install pip --upgrade`` to upgrade pip. Check pip version with ``pip --version``. +.. _release-5.7.7: + +5.7.7 +----- + +- Fix regression in restarting kernels in 5.7.5. + The restart handler would return before restart was completed. +- Further improve compatibility with tornado 6 with improved + checks for when websockets are closed. +- Fix regression in 5.7.6 on Windows where .js files could have the wrong mime-type. + .. _release-5.7.6: 5.7.6 diff --git a/notebook/base/zmqhandlers.py b/notebook/base/zmqhandlers.py index 7d0538fce..327fdd559 100644 --- a/notebook/base/zmqhandlers.py +++ b/notebook/base/zmqhandlers.py @@ -11,7 +11,8 @@ from urllib.parse import urlparse import tornado from tornado import gen, ioloop, web -from tornado.websocket import WebSocketHandler +from tornado.iostream import StreamClosedError +from tornado.websocket import WebSocketHandler, WebSocketClosedError from jupyter_client.session import Session from jupyter_client.jsonutil import date_default, extract_dates @@ -181,8 +182,13 @@ class WebSocketMixin(object): self.log.warning("WebSocket ping timeout after %i ms.", since_last_pong) self.close() return + try: + self.ping(b'') + except (StreamClosedError, WebSocketClosedError): + # websocket has been closed, stop pinging + self.ping_callback.stop() + return - self.ping(b'') self.last_ping = now def on_pong(self, data): @@ -242,8 +248,14 @@ class ZMQStreamHandler(WebSocketMixin, WebSocketHandler): msg = self._reserialize_reply(msg_list, channel=channel) except Exception: self.log.critical("Malformed message: %r" % msg_list, exc_info=True) - else: + return + + try: self.write_message(msg, binary=isinstance(msg, bytes)) + except (StreamClosedError, WebSocketClosedError): + self.log.warning("zmq message arrived on closed channel") + self.close() + return class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler): diff --git a/notebook/services/kernels/kernelmanager.py b/notebook/services/kernels/kernelmanager.py index fa52b5dfb..b072e014b 100644 --- a/notebook/services/kernels/kernelmanager.py +++ b/notebook/services/kernels/kernelmanager.py @@ -342,7 +342,8 @@ class MappingKernelManager(MultiKernelManager): channel.on_recv(on_reply) loop = IOLoop.current() timeout = loop.add_timeout(loop.time() + self.kernel_info_timeout, on_timeout) - raise gen.Return(future) + # wait for restart to complete + yield future def notify_connect(self, kernel_id): """Notice a new connection to a kernel"""