Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kernel subshells (JEP91) implementation #1249

Merged
merged 37 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4ea2d04
Separate thread to handle incoming shell channel messages
ianthomas23 May 8, 2024
b801b79
Add supported_features entry to kernel_info_reply
ianthomas23 May 8, 2024
0ddc1b7
Dummy subshell control message implementations
ianthomas23 May 8, 2024
17bd0f6
SubshellCache
ianthomas23 May 10, 2024
62e5d21
Subshell threads with correct lifetime but don't yet execute code
ianthomas23 May 10, 2024
2f8273b
Extract subshell_id, and handle message in correct subshell
ianthomas23 May 13, 2024
1cc8892
Add subshell test_execution_count
ianthomas23 May 22, 2024
f5b664d
Use dataclass for Subshell, clean up correctly
ianthomas23 May 22, 2024
c3fd89e
Test can create subshell whilst main subshell is executing
ianthomas23 May 22, 2024
7fc1d6e
Add %subshell magic
ianthomas23 May 23, 2024
b8b7af5
Temporary mutex for execute_reply from subshells
ianthomas23 May 29, 2024
7dd3407
Process subshell control messages in SubshellCache
ianthomas23 May 30, 2024
27ead02
Send shell reply messages via shell channel thread
ianthomas23 Jun 5, 2024
1e79f4c
Poll subshell inproc pair sockets in SubshellManager
ianthomas23 Jun 12, 2024
365d231
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 13, 2024
90c3a20
Better error checking
ianthomas23 Jun 13, 2024
2fa7365
Pin anyio <= 4.3.0
ianthomas23 Jun 13, 2024
ad32ea7
Remove anyio pin following fix in PR 1253
ianthomas23 Jul 1, 2024
f498045
Fix type annotations on old python
ianthomas23 Jul 1, 2024
48f7630
Make tests more robust
ianthomas23 Jul 1, 2024
c79ba79
Isolate each subshell test
ianthomas23 Aug 7, 2024
97e3e91
Avoid high CPU load when waiting for subshell reply messages
ianthomas23 Sep 12, 2024
e19273c
Replace use of zmq Poller with better anyio task handling
ianthomas23 Sep 13, 2024
a050784
Wrap sending via shell_socket with a lock
ianthomas23 Sep 13, 2024
9669fcd
More type annotations
ianthomas23 Sep 13, 2024
b72d1da
Ensure abort reply messages are sent via the subshell manager
ianthomas23 Sep 17, 2024
e4fa75d
Add modules to docs API
ianthomas23 Sep 17, 2024
a708e0e
Increase timings of test_subshells::test_execution_counts
ianthomas23 Sep 17, 2024
2a91bcd
Use _tasks_and_args in BaseThread
ianthomas23 Oct 2, 2024
4bcd59e
Use super when calling base class constructors
ianthomas23 Oct 2, 2024
b644f9e
Improve thread classes
ianthomas23 Oct 2, 2024
924015a
Always return supported_features in kernel_info
ianthomas23 Oct 2, 2024
a1fb1de
Make _supports_kernel_subshells a property
ianthomas23 Oct 2, 2024
be5c83a
Clarify socket=None in process_shell_message
ianthomas23 Oct 2, 2024
9109cc8
Improved use of thread names
ianthomas23 Oct 2, 2024
d17c77f
Small changes
ianthomas23 Oct 2, 2024
5715dd0
More type annotations
ianthomas23 Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/api/ipykernel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,30 @@ Submodules
:show-inheritance:


.. automodule:: ipykernel.shellchannel
:members:
:undoc-members:
:show-inheritance:


.. automodule:: ipykernel.subshell
:members:
:undoc-members:
:show-inheritance:


.. automodule:: ipykernel.subshell_manager
:members:
:undoc-members:
:show-inheritance:


.. automodule:: ipykernel.thread
:members:
:undoc-members:
:show-inheritance:


.. automodule:: ipykernel.trio_runner
:members:
:undoc-members:
Expand Down
30 changes: 4 additions & 26 deletions ipykernel/control.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
"""A thread for a control channel."""
from threading import Event, Thread

from anyio import create_task_group, run, to_thread
from .thread import BaseThread

CONTROL_THREAD_NAME = "Control"


class ControlThread(Thread):
class ControlThread(BaseThread):
"""A thread for a control channel."""

def __init__(self, **kwargs):
"""Initialize the thread."""
Thread.__init__(self, name=CONTROL_THREAD_NAME, **kwargs)
self.pydev_do_not_trace = True
self.is_pydev_daemon_thread = True
self.__stop = Event()
self._task = None

def set_task(self, task):
self._task = task
super().__init__(name=CONTROL_THREAD_NAME, **kwargs)

def run(self):
"""Run the thread."""
self.name = CONTROL_THREAD_NAME
Copy link
Member

@Carreau Carreau Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is unnecessary now Thread have setter/getter and super().__init__ should set the private name directly.

Maybe try to put an assert ==, and if test are passing, just remove the override of the run method ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the name duplication in b644f9e7 and 9109cc8 without causing any problems.

run(self._main)

async def _main(self):
async with create_task_group() as tg:
if self._task is not None:
tg.start_soon(self._task)
await to_thread.run_sync(self.__stop.wait)
tg.cancel_scope.cancel()

def stop(self):
"""Stop the thread.

This method is threadsafe.
"""
self.__stop.set()
super().run()
8 changes: 8 additions & 0 deletions ipykernel/kernelapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
from .iostream import IOPubThread
from .ipkernel import IPythonKernel
from .parentpoller import ParentPollerUnix, ParentPollerWindows
from .shellchannel import ShellChannelThread
from .zmqshell import ZMQInteractiveShell

# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -143,6 +144,7 @@ class IPKernelApp(BaseIPythonApplication, InteractiveShellApp, ConnectionFileMix
iopub_socket = Any()
iopub_thread = Any()
control_thread = Any()
shell_channel_thread = Any()

_ports = Dict()

Expand Down Expand Up @@ -367,6 +369,7 @@ def init_control(self, context):
self.control_socket.router_handover = 1

self.control_thread = ControlThread(daemon=True)
self.shell_channel_thread = ShellChannelThread(context, self.shell_socket, daemon=True)

def init_iopub(self, context):
"""Initialize the iopub channel."""
Expand Down Expand Up @@ -406,6 +409,10 @@ def close(self):
self.log.debug("Closing control thread")
self.control_thread.stop()
self.control_thread.join()
if self.shell_channel_thread and self.shell_channel_thread.is_alive():
self.log.debug("Closing shell channel thread")
self.shell_channel_thread.stop()
self.shell_channel_thread.join()

if self.debugpy_socket and not self.debugpy_socket.closed:
self.debugpy_socket.close()
Expand Down Expand Up @@ -562,6 +569,7 @@ def init_kernel(self):
debug_shell_socket=self.debug_shell_socket,
shell_socket=self.shell_socket,
control_thread=self.control_thread,
shell_channel_thread=self.shell_channel_thread,
iopub_thread=self.iopub_thread,
iopub_socket=self.iopub_socket,
stdin_socket=self.stdin_socket,
Expand Down
Loading
Loading