Skip to content

Commit

Permalink
Fix interrupt
Browse files Browse the repository at this point in the history
  • Loading branch information
garlandz-db committed Feb 28, 2023
1 parent d579a38 commit b9225a3
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 16 deletions.
26 changes: 15 additions & 11 deletions ipykernel/kernelbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ async def comm_info_request(self, stream, ident, parent):
msg = self.session.send(stream, "comm_info_reply", reply_content, parent, ident)
self.log.debug("%s", msg)

def _send_interupt_children(self):
def _send_interrupt_children(self):
if os.name == "nt":
self.log.error("Interrupt message not supported on Windows")
else:
Expand All @@ -892,20 +892,24 @@ def _send_interupt_children(self):
# Prefer process-group over process
# but only if the kernel is the leader of the process group
if pgid and pgid == pid and hasattr(os, "killpg"):
try:
os.killpg(pgid, SIGINT)
return
except OSError:
pass
try:
os.killpg(pgid, SIGINT)
else:
os.kill(pid, SIGINT)
except OSError:
pass

async def interrupt_request(self, stream, ident, parent):
"""Handle an interrupt request."""
self._send_interupt_children()
content = parent["content"]
try:
self._send_interrupt_children()
content = { "status": "ok" }
except OSError as err:
import traceback
content = {
"status": "error",
"traceback": traceback.format_stack(),
"ename": str(type(err).__name__),
"evalue": str(err),
}

self.session.send(stream, "interrupt_reply", content, parent, ident=ident)
return

Expand Down
2 changes: 1 addition & 1 deletion ipykernel/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ async def _wait_for_msg(self):
_, msg = self.session.feed_identities(self._reply)
return self.session.deserialize(msg)

def _send_interupt_children(self):
def _send_interrupt_children(self):
# override to prevent deadlock
pass

Expand Down
13 changes: 12 additions & 1 deletion ipykernel/tests/test_ipkernel_direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,20 @@ async def test_comm_info_request(ipkernel):


async def test_direct_interrupt_request(ipkernel):
reply = await ipkernel.test_shell_message("interrupt_request", {})
reply = await ipkernel.test_control_message("interrupt_request", {})
assert reply["header"]["msg_type"] == "interrupt_reply"
assert reply["content"] == { "status": "ok" }

# test failure on interrupt request
def raiseOSError():
raise OSError("evalue")
ipkernel._send_interrupt_children = raiseOSError
reply = await ipkernel.test_control_message("interrupt_request", {})
assert reply["header"]["msg_type"] == "interrupt_reply"
assert reply["content"]["status"] == "error"
assert reply["content"]["ename"] == "OSError"
assert reply["content"]["evalue"] == "evalue"
assert len(reply["content"]["traceback"]) > 0

# TODO: this causes deadlock
# async def test_direct_shutdown_request(ipkernel):
Expand Down
18 changes: 15 additions & 3 deletions ipykernel/tests/test_kernel_direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,20 @@ async def test_comm_info_request(kernel):


async def test_direct_interrupt_request(kernel):
reply = await kernel.test_shell_message("interrupt_request", {})
reply = await kernel.test_control_message("interrupt_request", {})
assert reply["header"]["msg_type"] == "interrupt_reply"
assert reply["content"] == { "status": "ok" }

# test failure on interrupt request
def raiseOSError():
raise OSError("evalue")
kernel._send_interrupt_children = raiseOSError
reply = await kernel.test_control_message("interrupt_request", {})
assert reply["header"]["msg_type"] == "interrupt_reply"
assert reply["content"]["status"] == "error"
assert reply["content"]["ename"] == "OSError"
assert reply["content"]["evalue"] == "evalue"
assert len(reply["content"]["traceback"]) > 0


async def test_direct_shutdown_request(kernel):
Expand Down Expand Up @@ -145,8 +157,8 @@ async def test_connect_request(kernel):
await kernel.connect_request(kernel.shell_stream, "foo", {})


async def test_send_interupt_children(kernel):
kernel._send_interupt_children()
async def test_send_interrupt_children(kernel):
kernel._send_interrupt_children()


# TODO: this causes deadlock
Expand Down

0 comments on commit b9225a3

Please sign in to comment.