-
Notifications
You must be signed in to change notification settings - Fork 287
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
Additional to the actual signal, send a message on the control port #294
Conversation
I was just looking for something similar to this, specifically for interrupting the kernel. Sending something over the control channel makes complete sense for this. It is a high priority message like the shutdown request. I don't see the benefit of sending the signals over sending a control message. Since we are at a higher level when working at the messaging level I think that the message doesn't need to be signal related anymore but rather simply an |
Cc @ivanov |
The rationale for signals is that the kernel may block message processing while it is executing user code, so a new message - even on the control channel - will not necessarily interrupt it. This is the case in the reference Python kernel, in the R kernel, and probably in all kernels built on the Python 'wrapper kernel' machinery, e.g. the bash kernel. We have also thought of adding messages for signals in a different context, to allow interrupting kernels running remotely. In that proposal, the frontend would send a signal message to a 'kernel nanny', a process running alongside the kernel, which would respond by sending a real Unix signal to the kernel process. IIRC it also came up there that some kernels would rather get an interrupt message than a signal, so it sounds like this might be worth doing. I'm not entirely convinced that sending both the signal and the message is the right thing to do. I don't yet have a concrete reason why not, but it feels a bit messy. Maybe kernels should have a way to declare whether they expect signals as real signals or as messages? |
Fair enough, I think an opt-in for the interrupt message is a good compromise. This would be backwards compatible as well which is a big plus. A My understanding of the control channel was that it should try to always be free to handle the high priority requests so when implementing the protocol I built with that in mind. It is on a separate thread and is therefore available to handle the request while the main shell is busy. |
The way we implement the control channel is that it can pre-empt queued messages on the shell channel. So if you send 10 cells for execution and then immediately ask the kernel to shut down, it will finish executing the first cell and shutdown before starting the other 9. But only signals pre-empt something that's already running. |
Is this behaviour of the control socket that a requirement, though? In Erlang I can easily interrupt and shut down execution while a cell is evaluated. I think I agree with scoping this down to an Is there any scenario in which sending the |
Not particularly, or at least it's not really specified, as far as I know. I'm just explaining the background of why signals are needed. :-)
I think it would be fine for a well-written kernel, but it could cause problems if a kernel author doesn't realise that they're getting both a signal and a message, and the kernel gets interrupted twice. I think it's common for kernels to print something like Allowing the kernel to pick either messages or signals will hopefully avoid this kind of confusion. |
Okay, I'll update the PR accordingly. |
Updated, please have another look. |
jupyter_client/manager.py
Outdated
if sys.platform == 'win32': | ||
from .win_interrupt import send_interrupt | ||
send_interrupt(self.kernel.win32_interrupt_event) | ||
self._send_signal_message(signal.SIGINT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the _send_signal_message
applies anymore. Might be left over from the initial commit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, fixed :)
Thanks. Since this involves a change to the message protocol, I'm going to start a discussion on the mailing list. |
@kevin-bates I want to make sure you see this, as this might be similar to what you did for remote kernel interrupt in "Enterprise Gateway" |
Thanks for the heads up @lresende. Yes, I had seen this a few days ago. The kernel launchers we use in Enterprise Gateway appear to follow the kernel nanny model described above, although our launchers actually house the target kernel. Btw, another advantage of a message-based interrupt is that the interrupt can span userid differences (while signals do not). This is more of an issue in a gateway environment since services like JupyterHub will launch the entire notebook server as the target user (retaining userid matches between kernel managers and kernel instances). |
This is a really great addition! I just have one question: Is it possible to add a |
@ccordoba12 What would you expect the kernel to do when it gets this message? @takluyver There doesn't seem to be any activity on the ML regarding this PR, maybe it helps if you just cc all relevant people here ... |
I think this is a fine addition. We just need to add this to the docs and bump the minor-revision of the spec. |
@filmor, kernels can be restarted after a shutdown: https://github.com/jupyter/jupyter_client/blob/master/jupyter_client/manager.py#L293 This would be useful for Spyder because people could interact with external kernels the same way as they would do with kernels started by Spyder itself. @minrk, what do you think? |
@ccordoba12 The shutdown_request looks like it already implements what you are asking about. The contents of this message has a What additional information are you looking for on top of that? |
Sorry, it seems you're right. I'll take a look at it more carefully. |
Thanks @filmor . I think the remaining thing to do is to bump the protocol version to 5.3. The places I'm aware of this are in the messaging doc near the top, and in |
I have no idea why this test fails ... |
- interrupt_mode="signal" is the default and current behaviour - With interrupt_mode="message", instead of a signal, a `interrupt_request` message on the control port will be sent
And I can not reproduce it locally. Any hints? |
It might be related to a change in zeromq, perhaps. @minrk this is the failure:
|
I think Min's changes in #304, which was just merged, probably fixed this. Closing and reopening to test. |
Yep, this looks better. Is there anything else to do? |
docs/kernels.rst
Outdated
- **interrupt_mode** (optional): May be either ``signal`` or ``message`` and | ||
specifies how a client is supposed to interrupt cell execution on this kernel, | ||
either by sending an interrupt ``signal`` via the operating system's | ||
signalling facilities (e.g. `SIGTERM` on POSIX systems), or by sending an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SIGTERM -> SIGINT
Thanks! |
@meeseeksdev backport |
There seem to be a conflict, please backport manually |
…the control port In Erlang I have only on POSIX and only in the newest version some control over the normal runtime signals, in particular SIGINT. However, I can easily pick up and process the respective message on the control socket to interrupt execution. Can this functionality be added? If yes, I'd continue and document the functionality and add tests. Maybe it would also be good to have the option of not sending an actual signal (via `os.kill`) at all. Signed-off-by: Thomas Kluyver <[email protected]>
Backported manually. |
In Erlang I have only on POSIX and only in the newest version some control over the normal runtime signals, in particular SIGINT. However, I can easily pick up and process the respective message on the control socket to interrupt execution.
Can this functionality be added? If yes, I'd continue and document the functionality and add tests. Maybe it would also be good to have the option of not sending an actual signal (via
os.kill
) at all.