Skip to content

Commit dc8d412

Browse files
committed
wip
1 parent ee2be0d commit dc8d412

File tree

2 files changed

+24
-24
lines changed

2 files changed

+24
-24
lines changed

jupyter_client/client.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
# Copyright (c) Jupyter Development Team.
33
# Distributed under the terms of the Modified BSD License.
44
import asyncio
5-
import atexit
65
import sys
76
import time
87
import typing as t
8+
import weakref
99
from functools import partial
1010
from getpass import getpass
1111
from queue import Empty
@@ -95,7 +95,8 @@ class KernelClient(ConnectionFileMixin):
9595

9696
def _context_default(self) -> zmq.asyncio.Context:
9797
context = zmq.asyncio.Context()
98-
atexit.register(context.destroy)
98+
# Use a finalizer to destroy the context.
99+
self._finalizer = weakref.finalize(self, context.destroy)
99100
return context
100101

101102
# The classes to use for the various channels

jupyter_client/multikernelmanager.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import socket
77
import typing as t
88
import uuid
9+
import weakref
910

1011
import zmq
1112
from traitlets import Any
@@ -95,8 +96,6 @@ def create_kernel_manager(*args: Any, **kwargs: Any) -> KernelManager:
9596
help="Share a single zmq.Context to talk to all my kernels",
9697
).tag(config=True)
9798

98-
_created_context = Bool(False)
99-
10099
context = Instance("zmq.Context")
101100

102101
_pending_kernels = Dict()
@@ -108,20 +107,18 @@ def _starting_kernels(self):
108107

109108
@default("context") # type:ignore[misc]
110109
def _context_default(self) -> zmq.Context:
111-
self._created_context = True
112-
return zmq.Context()
113-
114-
def __del__(self):
115-
if self._created_context and self.context and not self.context.closed:
116-
if self.log:
117-
self.log.debug("Destroying zmq context for %s", self)
118-
self.context.destroy()
119-
try:
120-
super_del = super().__del__
121-
except AttributeError:
122-
pass
123-
else:
124-
super_del()
110+
context = zmq.Context()
111+
# Use a finalizer to destroy the context.
112+
# self._finalizer = weakref.finalize(self, context.destroy)
113+
114+
raise ValueError('Notes here')
115+
"""
116+
The finalizer hangs because the context can't be destroyed.
117+
There are two other things that are probably contributing:
118+
- There is an open kernel subprocess at shutdown that is raising a warning on __del__
119+
- We are not properly canceling the _add_kernel_when_ready task
120+
"""
121+
return context
125122

126123
connection_dir = Unicode("")
127124

@@ -209,15 +206,15 @@ async def _async_start_kernel(self, kernel_name: t.Optional[str] = None, **kwarg
209206
kwargs['kernel_id'] = kernel_id # Make kernel_id available to manager and provisioner
210207

211208
starter = ensure_async(km.start_kernel(**kwargs))
212-
fut = asyncio.ensure_future(self._add_kernel_when_ready(kernel_id, km, starter))
213-
self._pending_kernels[kernel_id] = fut
209+
task = asyncio.create_task(self._add_kernel_when_ready(kernel_id, km, starter))
210+
self._pending_kernels[kernel_id] = task
214211
# Handling a Pending Kernel
215212
if self._using_pending_kernels():
216213
# If using pending kernels, do not block
217214
# on the kernel start.
218215
self._kernels[kernel_id] = km
219216
else:
220-
await fut
217+
await task
221218
# raise an exception if one occurred during kernel startup.
222219
if km.ready.exception():
223220
raise km.ready.exception() # type: ignore
@@ -246,9 +243,9 @@ async def _async_shutdown_kernel(
246243
self.log.info("Kernel shutdown: %s" % kernel_id)
247244
# If the kernel is still starting, wait for it to be ready.
248245
if kernel_id in self._pending_kernels:
249-
kernel = self._pending_kernels[kernel_id]
246+
task = self._pending_kernels[kernel_id]
250247
try:
251-
await kernel
248+
await task
252249
km = self.get_kernel(kernel_id)
253250
await t.cast(asyncio.Future, km.ready)
254251
except Exception:
@@ -311,7 +308,9 @@ async def _async_shutdown_all(self, now: bool = False) -> None:
311308
for km in kms:
312309
try:
313310
await km.ready
314-
except Exception:
311+
except asyncio.exceptions.CancelledError:
312+
self._pending_kernels[km.kernel_id].cancel()
313+
except Exception as e:
315314
# Will have been logged in _add_kernel_when_ready
316315
pass
317316

0 commit comments

Comments
 (0)