Skip to content

Commit e899ef1

Browse files
committed
Send the shutdown message over the control channel in client.py.
1 parent 4f7c825 commit e899ef1

File tree

1 file changed

+29
-4
lines changed

1 file changed

+29
-4
lines changed

jupyter_client/client.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ def validate_string_dict(dct):
3535
class KernelClient(ConnectionFileMixin):
3636
"""Communicates with a single kernel on any host via zmq channels.
3737
38-
There are four channels associated with each kernel:
38+
There are five channels associated with each kernel:
3939
4040
* shell: for request/reply calls to the kernel.
4141
* iopub: for the kernel to publish results to frontends.
4242
* hb: for monitoring the kernel's heartbeat.
4343
* stdin: for frontends to reply to raw_input calls in the kernel.
44+
* control: for kernel management calls to the kernel.
4445
4546
The messages that can be sent on these channels are exposed as methods of the
4647
client (KernelClient.execute, complete, history, etc.). These methods only
@@ -58,12 +59,14 @@ def _context_default(self):
5859
iopub_channel_class = Type(ChannelABC)
5960
stdin_channel_class = Type(ChannelABC)
6061
hb_channel_class = Type(HBChannelABC)
62+
control_channel_class = Type(ChannelABC)
6163

6264
# Protected traits
6365
_shell_channel = Any()
6466
_iopub_channel = Any()
6567
_stdin_channel = Any()
6668
_hb_channel = Any()
69+
_control_channel = Any()
6770

6871
# flag for whether execute requests should be allowed to call raw_input:
6972
allow_stdin = True
@@ -84,11 +87,15 @@ def get_stdin_msg(self, *args, **kwargs):
8487
"""Get a message from the stdin channel"""
8588
return self.stdin_channel.get_msg(*args, **kwargs)
8689

90+
def get_control_msg(self, *args, **kwargs):
91+
"""Get a message from the control channel"""
92+
return self.control_channel.get_msg(*args, **kwargs)
93+
8794
#--------------------------------------------------------------------------
8895
# Channel management methods
8996
#--------------------------------------------------------------------------
9097

91-
def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):
98+
def start_channels(self, shell=True, iopub=True, stdin=True, hb=True, control=True):
9299
"""Starts the channels for this kernel.
93100
94101
This will create the channels if they do not exist and then start
@@ -109,6 +116,9 @@ def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):
109116
self.allow_stdin = False
110117
if hb:
111118
self.hb_channel.start()
119+
if control:
120+
self.control_channel.start()
121+
self.kernel_info()
112122

113123
def stop_channels(self):
114124
"""Stops all the running channels for this kernel.
@@ -123,12 +133,15 @@ def stop_channels(self):
123133
self.stdin_channel.stop()
124134
if self.hb_channel.is_alive():
125135
self.hb_channel.stop()
136+
if self.control_channel.is_alive():
137+
self.control_channel.stop()
126138

127139
@property
128140
def channels_running(self):
129141
"""Are any of the channels created and running?"""
130142
return (self.shell_channel.is_alive() or self.iopub_channel.is_alive() or
131-
self.stdin_channel.is_alive() or self.hb_channel.is_alive())
143+
self.stdin_channel.is_alive() or self.hb_channel.is_alive() or
144+
self.control_channel.is_alive())
132145

133146
ioloop = None # Overridden in subclasses that use pyzmq event loop
134147

@@ -179,6 +192,18 @@ def hb_channel(self):
179192
)
180193
return self._hb_channel
181194

195+
@property
196+
def control_channel(self):
197+
"""Get the control channel object for this kernel."""
198+
if self._control_channel is None:
199+
url = self._make_url('control')
200+
self.log.debug("connecting control channel to %s", url)
201+
socket = self.connect_control(identity=self.session.bsession)
202+
self._control_channel = self.control_channel_class(
203+
socket, self.session, self.ioloop
204+
)
205+
return self._control_channel
206+
182207
def is_alive(self):
183208
"""Is the kernel process still running?"""
184209
from .manager import KernelManager
@@ -401,7 +426,7 @@ def shutdown(self, restart=False):
401426
# Send quit message to kernel. Once we implement kernel-side setattr,
402427
# this should probably be done that way, but for now this will do.
403428
msg = self.session.msg('shutdown_request', {'restart':restart})
404-
self.shell_channel.send(msg)
429+
self.control_channel.send(msg)
405430
return msg['header']['msg_id']
406431

407432
def is_complete(self, code):

0 commit comments

Comments
 (0)