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

Add Support for Message Based Interrupt #741

Merged
merged 1 commit into from
Aug 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 26 additions & 1 deletion ipykernel/kernelbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import itertools
import logging
import inspect
import os
from signal import signal, default_int_handler, SIGINT
import sys
import time
Expand Down Expand Up @@ -198,7 +199,7 @@ def _parent_header(self):
'inspect_request', 'history_request',
'comm_info_request', 'kernel_info_request',
'connect_request', 'shutdown_request',
'is_complete_request',
'is_complete_request', 'interrupt_request',
# deprecated:
'apply_request',
]
Expand Down Expand Up @@ -780,6 +781,30 @@ async def comm_info_request(self, stream, ident, parent):
reply_content, parent, ident)
self.log.debug("%s", msg)

async def interrupt_request(self, stream, ident, parent):
pid = os.getpid()
pgid = os.getpgid(pid)

if os.name == "nt":
self.log.error("Interrupt message not supported on Windows")

else:
# Prefer process-group over process
if pgid and hasattr(os, "killpg"):
try:
os.killpg(pgid, SIGINT)
return
except OSError:
pass
try:
os.kill(pid, SIGINT)
except OSError:
pass

content = parent['content']
self.session.send(stream, 'interrupt_reply', content, parent, ident=ident)
return

async def shutdown_request(self, stream, ident, parent):
content = self.do_shutdown(parent['content']['restart'])
if inspect.isawaitable(content):
Expand Down
20 changes: 20 additions & 0 deletions ipykernel/tests/test_kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,26 @@ def test_interrupt_during_input():
validate_message(reply, 'execute_reply', msg_id)


@pytest.mark.skipif(
os.name == "nt",
reason="Message based interrupt not supported on Windows"
)
def test_interrupt_with_message():
"""

"""
with new_kernel() as kc:
km = kc.parent
km.kernel_spec.interrupt_mode = "message"
msg_id = kc.execute("input()")
time.sleep(1) # Make sure it's actually waiting for input.
km.interrupt_kernel()
from .test_message_spec import validate_message
# If we failed to interrupt interrupt, this will timeout:
reply = get_reply(kc, msg_id, TIMEOUT)
validate_message(reply, 'execute_reply', msg_id)


@pytest.mark.skipif(
version.parse(IPython.__version__) < version.parse("7.14.0"),
reason="Need new IPython"
Expand Down