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

Fix failure to shutdown on keyboard interrupt #3982

Merged
merged 3 commits into from
Dec 7, 2020

Conversation

MetRonnie
Copy link
Member

@MetRonnie MetRonnie commented Dec 7, 2020

These changes close #3946

Ctrl+C was failing to shutdown the scheduler on Python 3.8+ due to the fact that asyncio.CanclledError changed from subclassing Exception to BaseException. See https://stackoverflow.com/a/60167684/3217306 and https://docs.python.org/3.8/library/asyncio-exceptions.html#asyncio.CancelledError

I'm new to asyncio, and there seems to be another way of handling signal interruptions: https://www.roguelynn.com/words/asyncio-graceful-shutdowns/. However, the changes I've made are very simple and seem to work.

Requirements check-list

  • I have read CONTRIBUTING.md and added my name as a Code Contributor.
  • Contains logically grouped changes (else tidy your branch by rebase).
  • Does not contain off-topic changes (use other PRs for other changes).
  • Does not need tests (I'm not sure we can test this?).
  • Appropriate change log entry included.
  • No documentation update required.
  • No dependency changes.

@MetRonnie MetRonnie added the bug Something is wrong :( label Dec 7, 2020
@MetRonnie MetRonnie added this to the cylc-8.0a3 milestone Dec 7, 2020
@MetRonnie MetRonnie self-assigned this Dec 7, 2020
Comment on lines -409 to -415
except KeyboardInterrupt as exc:
try:
await scheduler.shutdown(exc)
except Exception as exc2:
# In case of exceptions in the shutdown method itself.
LOG.exception(exc2)
raise exc2 from None
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this anymore as the shutdown is handled in scheduler.run() or scheduler.start_scheduler()

@MetRonnie MetRonnie added the small label Dec 7, 2020
@@ -643,7 +643,7 @@ async def run(self):
await self.configure()
await self.start_servers()
await self.log_start()
except Exception as exc:
except (KeyboardInterrupt, asyncio.CancelledError, Exception) as exc:
await self.shutdown(exc)
Copy link
Member

@oliver-sanders oliver-sanders Dec 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to copy over the try/except to ensure that shutdown traceback gets dumped to the flow log if not handled by scheduler_cli.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MetRonnie two approvals, but will let you reply this one before I merge it (happy if you or @oliver-sanders merge it after you've taken a look on this one too 👍 )

Copy link
Member

@oliver-sanders oliver-sanders left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me, tested 3.7/3.8.

(I'm not sure we can test this?)

It's do-able via bash though fiddly, we used to do this for cylc scan (tests/functional/cylc-scan/02-sigstop.t).

Should be able to do via Python though, could try writing an integration test and raising KeyboardInterrupt from within the Scheduler, not 100% sure what would happen but worth a try:

reg = flow(one_conf)
schd = scheduler(reg)
async with run(schd) as flow_log:
    # await asyncio.sleep(0)  # try this if it doesn't work
    raise KeyboardInterrupt()
assert flow_log.record_tuples[-1] == [...]

Copy link
Member

@kinow kinow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worked like a charm. Switched to this branch, re-installed my venv, started five. Stopped it, and it exited nicely 👍

Thanks @MetRonnie !

@MetRonnie
Copy link
Member Author

Having a go at the integration test

@MetRonnie
Copy link
Member Author

Couldn't get the integration test to work. It seemed like the KeyboardInterrupt caused the test to quit, but I didn't spend too much time looking into it

elif isinstance(reason, SchedulerError):
LOG.error('Suite shutting down - %s', reason)
LOG.error(f'Suite shutting down - {reason}')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

@hjoliver hjoliver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me too; thanks @MetRonnie 👍

I'll merge this now, a test for this isn't super-critical. We developers are likely to notice quickly if this breaks in future.

@hjoliver hjoliver merged commit db993d5 into cylc:master Dec 7, 2020
@MetRonnie MetRonnie deleted the keyboard-interrupt branch December 8, 2020 09:28
@hjoliver hjoliver modified the milestones: cylc-8.0a3, cylc-8.0b0 Feb 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is wrong :( small
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Scheduler keeps running after CTRL + C (Py3.8)
4 participants