##// END OF EJS Templates
back to development
back to development

File last commit:

r10334:d2d10ca9
r18802:bc858e72
Show More
restarter.py
114 lines | 3.9 KiB | text/x-python | PythonLexer
MinRK
cleanup boundaries of MultiKernelManager and KernelRestarter classes...
r10295 """A basic kernel monitor with autorestarting.
This watches a kernel's state using KernelManager.is_alive and auto
restarts the kernel if it dies.
It is an incomplete base class, and must be subclassed.
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2013 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from IPython.config.configurable import LoggingConfigurable
from IPython.utils.traitlets import (
MinRK
change how failed restarts are detected...
r10334 Instance, Float, Dict, Bool, Integer,
MinRK
cleanup boundaries of MultiKernelManager and KernelRestarter classes...
r10295 )
#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------
class KernelRestarter(LoggingConfigurable):
"""Monitor and autorestart a kernel."""
kernel_manager = Instance('IPython.kernel.KernelManager')
time_to_dead = Float(3.0, config=True,
help="""Kernel heartbeat interval in seconds."""
)
MinRK
fire 'dead' callbacks when kernel dies before its first heartbeat
r10314
MinRK
change how failed restarts are detected...
r10334 restart_limit = Integer(5, config=True,
help="""The number of consecutive autorestarts before the kernel is presumed dead."""
)
MinRK
fix inverted default value for KR._restarting
r10318 _restarting = Bool(False)
MinRK
change how failed restarts are detected...
r10334 _restart_count = Integer(0)
MinRK
fire 'dead' callbacks when kernel dies before its first heartbeat
r10314
MinRK
expose restart callbacks via KernelManager
r10313 callbacks = Dict()
def _callbacks_default(self):
return dict(restart=[], dead=[])
MinRK
cleanup boundaries of MultiKernelManager and KernelRestarter classes...
r10295
def start(self):
"""Start the polling of the kernel."""
raise NotImplementedError("Must be implemented in a subclass")
def stop(self):
"""Stop the kernel polling."""
raise NotImplementedError("Must be implemented in a subclass")
MinRK
expose restart callbacks via KernelManager
r10313 def add_callback(self, f, event='restart'):
"""register a callback to fire on a particular event
Possible values for event:
'restart' (default): kernel has died, and will be restarted.
'dead': restart has failed, kernel will be left dead.
"""
self.callbacks[event].append(f)
def remove_callback(self, f, event='restart'):
"""unregister a callback to fire on a particular event
Possible values for event:
'restart' (default): kernel has died, and will be restarted.
'dead': restart has failed, kernel will be left dead.
MinRK
cleanup boundaries of MultiKernelManager and KernelRestarter classes...
r10295
MinRK
expose restart callbacks via KernelManager
r10313 """
MinRK
cleanup boundaries of MultiKernelManager and KernelRestarter classes...
r10295 try:
MinRK
expose restart callbacks via KernelManager
r10313 self.callbacks[event].remove(f)
MinRK
cleanup boundaries of MultiKernelManager and KernelRestarter classes...
r10295 except ValueError:
pass
MinRK
fire 'dead' callbacks when kernel dies before its first heartbeat
r10314 def _fire_callbacks(self, event):
"""fire our callbacks for a particular event"""
for callback in self.callbacks[event]:
try:
callback()
except Exception as e:
self.log.error("KernelRestarter: %s callback %r failed", event, callback, exc_info=True)
MinRK
cleanup boundaries of MultiKernelManager and KernelRestarter classes...
r10295 def poll(self):
self.log.debug('Polling kernel...')
if not self.kernel_manager.is_alive():
MinRK
fire 'dead' callbacks when kernel dies before its first heartbeat
r10314 if self._restarting:
MinRK
change how failed restarts are detected...
r10334 self._restart_count += 1
else:
self._restart_count = 1
if self._restart_count >= self.restart_limit:
MinRK
fire 'dead' callbacks when kernel dies before its first heartbeat
r10314 self.log.warn("KernelRestarter: restart failed")
self._fire_callbacks('dead')
self._restarting = False
MinRK
change how failed restarts are detected...
r10334 self._restart_count = 0
MinRK
cleanup restart logic...
r10320 self.stop()
MinRK
fire 'dead' callbacks when kernel dies before its first heartbeat
r10314 else:
MinRK
change how failed restarts are detected...
r10334 self.log.info('KernelRestarter: restarting kernel (%i/%i)',
self._restart_count,
self.restart_limit
)
MinRK
fire 'dead' callbacks when kernel dies before its first heartbeat
r10314 self._fire_callbacks('restart')
self.kernel_manager.restart_kernel(now=True)
self._restarting = True
MinRK
cleanup restart logic...
r10320 else:
if self._restarting:
self.log.debug("KernelRestarter: restart apparently succeeded")
self._restarting = False