Skip to content

Commit b9225a3

Browse files
committed
Fix interrupt
1 parent d579a38 commit b9225a3

File tree

4 files changed

+43
-16
lines changed

4 files changed

+43
-16
lines changed

ipykernel/kernelbase.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ async def comm_info_request(self, stream, ident, parent):
883883
msg = self.session.send(stream, "comm_info_reply", reply_content, parent, ident)
884884
self.log.debug("%s", msg)
885885

886-
def _send_interupt_children(self):
886+
def _send_interrupt_children(self):
887887
if os.name == "nt":
888888
self.log.error("Interrupt message not supported on Windows")
889889
else:
@@ -892,20 +892,24 @@ def _send_interupt_children(self):
892892
# Prefer process-group over process
893893
# but only if the kernel is the leader of the process group
894894
if pgid and pgid == pid and hasattr(os, "killpg"):
895-
try:
896-
os.killpg(pgid, SIGINT)
897-
return
898-
except OSError:
899-
pass
900-
try:
895+
os.killpg(pgid, SIGINT)
896+
else:
901897
os.kill(pid, SIGINT)
902-
except OSError:
903-
pass
904898

905899
async def interrupt_request(self, stream, ident, parent):
906900
"""Handle an interrupt request."""
907-
self._send_interupt_children()
908-
content = parent["content"]
901+
try:
902+
self._send_interrupt_children()
903+
content = { "status": "ok" }
904+
except OSError as err:
905+
import traceback
906+
content = {
907+
"status": "error",
908+
"traceback": traceback.format_stack(),
909+
"ename": str(type(err).__name__),
910+
"evalue": str(err),
911+
}
912+
909913
self.session.send(stream, "interrupt_reply", content, parent, ident=ident)
910914
return
911915

ipykernel/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ async def _wait_for_msg(self):
9999
_, msg = self.session.feed_identities(self._reply)
100100
return self.session.deserialize(msg)
101101

102-
def _send_interupt_children(self):
102+
def _send_interrupt_children(self):
103103
# override to prevent deadlock
104104
pass
105105

ipykernel/tests/test_ipkernel_direct.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,20 @@ async def test_comm_info_request(ipkernel):
9090

9191

9292
async def test_direct_interrupt_request(ipkernel):
93-
reply = await ipkernel.test_shell_message("interrupt_request", {})
93+
reply = await ipkernel.test_control_message("interrupt_request", {})
9494
assert reply["header"]["msg_type"] == "interrupt_reply"
95+
assert reply["content"] == { "status": "ok" }
9596

97+
# test failure on interrupt request
98+
def raiseOSError():
99+
raise OSError("evalue")
100+
ipkernel._send_interrupt_children = raiseOSError
101+
reply = await ipkernel.test_control_message("interrupt_request", {})
102+
assert reply["header"]["msg_type"] == "interrupt_reply"
103+
assert reply["content"]["status"] == "error"
104+
assert reply["content"]["ename"] == "OSError"
105+
assert reply["content"]["evalue"] == "evalue"
106+
assert len(reply["content"]["traceback"]) > 0
96107

97108
# TODO: this causes deadlock
98109
# async def test_direct_shutdown_request(ipkernel):

ipykernel/tests/test_kernel_direct.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,20 @@ async def test_comm_info_request(kernel):
6969

7070

7171
async def test_direct_interrupt_request(kernel):
72-
reply = await kernel.test_shell_message("interrupt_request", {})
72+
reply = await kernel.test_control_message("interrupt_request", {})
7373
assert reply["header"]["msg_type"] == "interrupt_reply"
74+
assert reply["content"] == { "status": "ok" }
75+
76+
# test failure on interrupt request
77+
def raiseOSError():
78+
raise OSError("evalue")
79+
kernel._send_interrupt_children = raiseOSError
80+
reply = await kernel.test_control_message("interrupt_request", {})
81+
assert reply["header"]["msg_type"] == "interrupt_reply"
82+
assert reply["content"]["status"] == "error"
83+
assert reply["content"]["ename"] == "OSError"
84+
assert reply["content"]["evalue"] == "evalue"
85+
assert len(reply["content"]["traceback"]) > 0
7486

7587

7688
async def test_direct_shutdown_request(kernel):
@@ -145,8 +157,8 @@ async def test_connect_request(kernel):
145157
await kernel.connect_request(kernel.shell_stream, "foo", {})
146158

147159

148-
async def test_send_interupt_children(kernel):
149-
kernel._send_interupt_children()
160+
async def test_send_interrupt_children(kernel):
161+
kernel._send_interrupt_children()
150162

151163

152164
# TODO: this causes deadlock

0 commit comments

Comments
 (0)