Skip to content

Commit e46f75b

Browse files
authored
Fix interrupt reply (#1101)
* Fix interrupt * . * . * . * .
1 parent 287184f commit e46f75b

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

ipykernel/kernelbase.py

+17-8
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:
@@ -894,18 +894,27 @@ def _send_interupt_children(self):
894894
if pgid and pgid == pid and hasattr(os, "killpg"):
895895
try:
896896
os.killpg(pgid, SIGINT)
897-
return
898897
except OSError:
899-
pass
900-
try:
898+
os.kill(pid, SIGINT)
899+
raise
900+
else:
901901
os.kill(pid, SIGINT)
902-
except OSError:
903-
pass
904902

905903
async def interrupt_request(self, stream, ident, parent):
906904
"""Handle an interrupt request."""
907-
self._send_interupt_children()
908-
content = parent["content"]
905+
content: t.Dict[str, t.Any] = {"status": "ok"}
906+
try:
907+
self._send_interrupt_children()
908+
except OSError as err:
909+
import traceback
910+
911+
content = {
912+
"status": "error",
913+
"traceback": traceback.format_stack(),
914+
"ename": str(type(err).__name__),
915+
"evalue": str(err),
916+
}
917+
909918
self.session.send(stream, "interrupt_reply", content, parent, ident=ident)
910919
return
911920

ipykernel/tests/conftest.py

+1-1
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

+14-1
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,21 @@ 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"}
96+
97+
# test failure on interrupt request
98+
def raiseOSError():
99+
raise OSError("evalue")
100+
101+
ipkernel._send_interrupt_children = raiseOSError
102+
reply = await ipkernel.test_control_message("interrupt_request", {})
103+
assert reply["header"]["msg_type"] == "interrupt_reply"
104+
assert reply["content"]["status"] == "error"
105+
assert reply["content"]["ename"] == "OSError"
106+
assert reply["content"]["evalue"] == "evalue"
107+
assert len(reply["content"]["traceback"]) > 0
95108

96109

97110
# TODO: this causes deadlock

ipykernel/tests/test_kernel_direct.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,21 @@ 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+
80+
kernel._send_interrupt_children = raiseOSError
81+
reply = await kernel.test_control_message("interrupt_request", {})
82+
assert reply["header"]["msg_type"] == "interrupt_reply"
83+
assert reply["content"]["status"] == "error"
84+
assert reply["content"]["ename"] == "OSError"
85+
assert reply["content"]["evalue"] == "evalue"
86+
assert len(reply["content"]["traceback"]) > 0
7487

7588

7689
async def test_direct_shutdown_request(kernel):
@@ -145,8 +158,8 @@ async def test_connect_request(kernel):
145158
await kernel.connect_request(kernel.shell_stream, "foo", {})
146159

147160

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

151164

152165
# TODO: this causes deadlock

0 commit comments

Comments
 (0)