Skip to content

Commit eb71bb3

Browse files
committed
Backport notebook PR
1 parent ca492c1 commit eb71bb3

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

jupyter_server/services/kernels/handlers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def _handle_kernel_info_reply(self, msg):
155155
156156
enabling msg spec adaptation, if necessary
157157
"""
158-
idents,msg = self.session.feed_identities(msg)
158+
idents, msg = self.session.feed_identities(msg)
159159
try:
160160
msg = self.session.deserialize(msg)
161161
except:

jupyter_server/services/kernels/kernelmanager.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from datetime import datetime, timedelta
1212
from functools import partial
1313
import os
14+
import time
1415

1516
from tornado import web
1617
from tornado.concurrent import Future
@@ -320,37 +321,62 @@ async def restart_kernel(self, kernel_id):
320321
await ensure_async(self.pinned_superclass.restart_kernel(self, kernel_id))
321322
kernel = self.get_kernel(kernel_id)
322323
# return a Future that will resolve when the kernel has successfully restarted
323-
channel = kernel.connect_shell()
324+
shell_channel = kernel.connect_shell()
325+
iopub_channel = kernel.connect_iopub()
324326
future = Future()
327+
info_future = Future()
328+
iopub_future = Future()
325329

326330
def finish():
327331
"""Common cleanup when restart finishes/fails for any reason."""
328-
if not channel.closed():
329-
channel.close()
330332
loop.remove_timeout(timeout)
331333
kernel.remove_restart_callback(on_restart_failed, 'dead')
332334

333-
def on_reply(msg):
335+
def on_shell_reply(msg):
334336
self.log.debug("Kernel info reply received: %s", kernel_id)
335-
finish()
336-
if not future.done():
337-
future.set_result(msg)
337+
shell_channel.close()
338+
if not info_future.done():
339+
info_future.set_result(msg)
340+
if iopub_future.done():
341+
finish()
342+
future.set_result(info_future.result())
343+
344+
def on_iopub(msg):
345+
self.log.debug("first IOPub received: %s", kernel_id)
346+
iopub_channel.close()
347+
if not iopub_future.done():
348+
iopub_future.set_result(None)
349+
if info_future.done():
350+
finish()
351+
future.set_result(info_future.result())
338352

339353
def on_timeout():
340354
self.log.warning("Timeout waiting for kernel_info_reply: %s", kernel_id)
355+
if not shell_channel.closed():
356+
shell_channel.close()
357+
if not iopub_channel.closed():
358+
iopub_channel.close()
341359
finish()
342360
if not future.done():
343361
future.set_exception(TimeoutError("Timeout waiting for restart"))
344362

345363
def on_restart_failed():
346364
self.log.warning("Restarting kernel failed: %s", kernel_id)
365+
if not shell_channel.closed():
366+
shell_channel.close()
367+
if not iopub_channel.closed():
368+
iopub_channel.close()
347369
finish()
348370
if not future.done():
349371
future.set_exception(RuntimeError("Restart failed"))
350372

351373
kernel.add_restart_callback(on_restart_failed, 'dead')
352-
kernel.session.send(channel, "kernel_info_request")
353-
channel.on_recv(on_reply)
374+
iopub_channel.on_recv(on_iopub)
375+
shell_channel.on_recv(on_shell_reply)
376+
while not future.done():
377+
time.sleep(0.2)
378+
# Nudge the kernel with kernel info requests until we get an IOPub message
379+
kernel.session.send(shell_channel, "kernel_info_request")
354380
loop = IOLoop.current()
355381
timeout = loop.add_timeout(loop.time() + self.kernel_info_timeout, on_timeout)
356382
return future

0 commit comments

Comments
 (0)