diff --git a/jupyter_server/services/kernels/handlers.py b/jupyter_server/services/kernels/handlers.py index 6e4d6989f3..e84b4e7ca4 100644 --- a/jupyter_server/services/kernels/handlers.py +++ b/jupyter_server/services/kernels/handlers.py @@ -7,6 +7,8 @@ import json import logging from textwrap import dedent +from traceback import format_tb +import traceback from ipython_genutils.py3compat import cast_unicode from jupyter_client import protocol_version as client_protocol_version @@ -79,7 +81,10 @@ async def post(self, kernel_id, action): try: await km.restart_kernel(kernel_id) except Exception as e: - self.log.error("Exception restarting kernel", exc_info=True) + message = "Exception restarting kernel" + self.log.error(message, exc_info=True) + traceback = format_tb(e.__traceback__) + self.write(json.dumps(dict(message=message, traceback=traceback))) self.set_status(500) else: model = await ensure_async(km.kernel_model(kernel_id)) @@ -326,6 +331,7 @@ async def pre_get(self): # We don't want to wait forever, because browsers don't take it well when # servers never respond to websocket connection requests. kernel = self.kernel_manager.get_kernel(self.kernel_id) + await kernel.ready self.session.key = kernel.session.key future = self.request_kernel_info() @@ -446,6 +452,7 @@ def on_message(self, msg): def _on_zmq_reply(self, stream, msg_list): idents, fed_msg_list = self.session.feed_identities(msg_list) msg = self.session.deserialize(fed_msg_list) + parent = msg["parent_header"] def write_stderr(error_message): diff --git a/jupyter_server/services/kernels/kernelmanager.py b/jupyter_server/services/kernels/kernelmanager.py index 02a1e4d346..074fa5b5b2 100644 --- a/jupyter_server/services/kernels/kernelmanager.py +++ b/jupyter_server/services/kernels/kernelmanager.py @@ -5,6 +5,7 @@ """ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. +import asyncio import os from collections import defaultdict from datetime import datetime @@ -51,6 +52,8 @@ def _default_kernel_manager_class(self): kernel_argv = List(Unicode()) + use_pending_kernels = True + root_dir = Unicode(config=True) _kernel_connections = Dict() @@ -209,7 +212,7 @@ async def start_kernel(self, kernel_id=None, path=None, **kwargs): kwargs["kernel_id"] = kernel_id kernel_id = await ensure_async(self.pinned_superclass.start_kernel(self, **kwargs)) self._kernel_connections[kernel_id] = 0 - self._kernel_ports[kernel_id] = self._kernels[kernel_id].ports + task = asyncio.create_task(self._get_ports(kernel_id)) self.start_watching_activity(kernel_id) self.log.info("Kernel started: %s" % kernel_id) self.log.debug("Kernel args: %r" % kwargs) @@ -233,6 +236,11 @@ async def start_kernel(self, kernel_id=None, path=None, **kwargs): return kernel_id + async def _get_ports(self, kernel_id): + km = self.get_kernel(kernel_id) + await km.ready + self._kernel_ports[kernel_id] = km.ports + def ports_changed(self, kernel_id): """Used by ZMQChannelsHandler to determine how to coordinate nudge and replays.