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

Re-introduce #539, fix abort to not abort non-execute requests #572

Merged
merged 6 commits into from
Dec 15, 2020
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
25 changes: 8 additions & 17 deletions ipykernel/kernelbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@

CONTROL_PRIORITY = 1
SHELL_PRIORITY = 10
ABORT_PRIORITY = 20


class Kernel(SingletonConfigurable):
Expand Down Expand Up @@ -182,10 +181,6 @@ def dispatch_control(self, msg):
# Set the parent message for side effects.
self.set_parent(idents, msg)
self._publish_status('busy')
if self._aborting:
self._send_abort_reply(self.control_stream, msg, idents)
self._publish_status('idle')
return

header = msg['header']
msg_type = header['msg_type']
Expand Down Expand Up @@ -233,16 +228,17 @@ def dispatch_shell(self, stream, msg):
self.set_parent(idents, msg)
self._publish_status('busy')

if self._aborting:
msg_type = msg['header']['msg_type']

# Only abort execute requests
if self._aborting and msg_type == 'execute_request':
self._send_abort_reply(stream, msg, idents)
self._publish_status('idle')
# flush to ensure reply is sent before
# handling the next request
stream.flush(zmq.POLLOUT)
return

msg_type = msg['header']['msg_type']

# Print some info about this message and leave a '--->' marker, so it's
# easier to trace visually the message chain when debugging. Each
# handler prints its message at the end.
Expand Down Expand Up @@ -792,16 +788,11 @@ def _abort_queues(self):
stream.flush()
self._aborting = True

self.schedule_dispatch(
ABORT_PRIORITY,
self._dispatch_abort,
)
def stop_aborting(f):
self.log.info("Finishing abort")
self._aborting = False

@gen.coroutine
def _dispatch_abort(self):
self.log.info("Finishing abort")
yield gen.sleep(self.stop_on_error_timeout)
self._aborting = False
self.io_loop.add_future(gen.sleep(self.stop_on_error_timeout), stop_aborting)

def _send_abort_reply(self, stream, msg, idents):
"""Send a reply to an aborted request"""
Expand Down
31 changes: 31 additions & 0 deletions ipykernel/tests/test_message_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ def check(self, d):
ExecuteReplyOkay().check(d)
elif d['status'] == 'error':
ExecuteReplyError().check(d)
elif d['status'] == 'aborted':
ExecuteReplyAborted().check(d)


class ExecuteReplyOkay(Reply):
Expand All @@ -122,11 +124,16 @@ class ExecuteReplyOkay(Reply):


class ExecuteReplyError(Reply):
status = Enum(('error',))
ename = Unicode()
evalue = Unicode()
traceback = List(Unicode())


class ExecuteReplyAborted(Reply):
status = Enum(('aborted',))


class InspectReply(Reply, MimeBundle):
found = Bool()

Expand Down Expand Up @@ -348,6 +355,30 @@ def test_execute_stop_on_error():
assert reply['content']['status'] == 'ok'


def test_non_execute_stop_on_error():
"""test that non-execute_request's are not aborted after an error"""
flush_channels()

fail = '\n'.join([
# sleep to ensure subsequent message is waiting in the queue to be aborted
'import time',
'time.sleep(0.5)',
'raise ValueError',
])
KC.execute(code=fail)
KC.kernel_info()
KC.comm_info()
KC.inspect(code="print")
reply = KC.get_shell_msg(timeout=TIMEOUT) # execute
assert reply['content']['status'] == 'error'
reply = KC.get_shell_msg(timeout=TIMEOUT) # kernel_info
assert reply['content']['status'] == 'ok'
reply = KC.get_shell_msg(timeout=TIMEOUT) # comm_info
assert reply['content']['status'] == 'ok'
reply = KC.get_shell_msg(timeout=TIMEOUT) # inspect
assert reply['content']['status'] == 'ok'


def test_user_expressions():
flush_channels()

Expand Down