Jupyterhub: use previous exit strategy for Windows

Windows doesn't have support for signal handling so it can't use the
signal handling capabilities of asyncio. Use the previous atexit
strategy on the Windows case instead.

Signed-off-by: Alejandro Del Castillo <alejandro.delcastillo@ni.com>
This commit is contained in:
Alejandro Del Castillo
2019-05-10 16:17:29 -05:00
parent e4d4e059bd
commit aaad55e076

View File

@@ -2420,22 +2420,30 @@ class JupyterHub(Application):
pc.start()
self.log.info("JupyterHub is now running at %s", self.proxy.public_url)
# Use atexit for Windows, it doesn't have signal handling support
if _mswindows:
atexit.register(self.atexit)
# register cleanup on both TERM and INT
self.init_signal()
def init_signal(self):
loop = asyncio.get_event_loop()
for s in (signal.SIGTERM, signal.SIGINT):
loop.add_signal_handler(
s, lambda s=s: asyncio.ensure_future(self.shutdown_cancel_tasks(s))
)
infosignals = [signal.SIGUSR1]
if hasattr(signal, 'SIGINFO'):
infosignals.append(signal.SIGINFO)
for s in infosignals:
loop.add_signal_handler(
s, lambda s=s: asyncio.ensure_future(self.log_status(s))
)
if not _mswindows:
loop.add_signal_handler(
s, lambda s=s: asyncio.ensure_future(self.shutdown_cancel_tasks(s))
)
else:
signal.signal(s, self.win_shutdown_cancel_tasks)
if not _mswindows:
infosignals = [signal.SIGUSR1]
if hasattr(signal, 'SIGINFO'):
infosignals.append(signal.SIGINFO)
for s in infosignals:
loop.add_signal_handler(
s, lambda s=s: asyncio.ensure_future(self.log_status(s))
)
async def log_status(self, sig):
"""Log current status, triggered by SIGINFO (^T in many terminals)"""
@@ -2443,6 +2451,24 @@ class JupyterHub(Application):
print_ps_info()
print_stacks()
def win_shutdown_cancel_tasks(self, signum, frame):
self.log.critical("Received signalnum %s, , initiating shutdown...", signum)
raise SystemExit(128 + signum)
_atexit_ran = False
def atexit(self):
"""atexit callback"""
if self._atexit_ran:
return
self._atexit_ran = True
# run the cleanup step (in a new loop, because the interrupted one is unclean)
asyncio.set_event_loop(asyncio.new_event_loop())
IOLoop.clear_current()
loop = IOLoop()
loop.make_current()
loop.run_sync(self.cleanup)
async def shutdown_cancel_tasks(self, sig):
"""Cancel all other tasks of the event loop and initiate cleanup"""
self.log.critical("Received signal %s, initiating shutdown...", sig.name)