##// END OF EJS Templates
More work on autorestarting.
Brian Granger -
Show More
@@ -41,22 +41,37 b' class KernelRestarter(LoggingConfigurable):'
41 help="""Kernel heartbeat interval in seconds."""
41 help="""Kernel heartbeat interval in seconds."""
42 )
42 )
43
43
44 _pcallback = None
45
44 def __init__(self, **kwargs):
46 def __init__(self, **kwargs):
45 super(KernelRestarter, self).__init__(**kwargs)
47 super(KernelRestarter, self).__init__(**kwargs)
46
48
47 def start(self):
49 def start(self):
48 self.pc = ioloop.PeriodicCallback(self.poll, self.time_to_dead, self.ioloop)
50 """Start the polling of the kernel."""
49 self.pc.start()
51 if self._pcallback is None:
52 self._pcallback = ioloop.PeriodicCallback(
53 self._poll, 1000*self.time_to_dead, self.ioloop
54 )
55 self._pcallback.start()
56
57 def stop(self):
58 """Stop the kernel polling."""
59 if self._pcallback is not None:
60 self._pcallback.stop()
50
61
51 def poll(self):
62 def clear(self):
63 """Clear the underlying PeriodicCallback."""
64 self.stop()
65 if self._pcallback is not None:
66 self._pcallback = None
67
68 def _poll(self):
52 if not self.kernel_manager.is_alive():
69 if not self.kernel_manager.is_alive():
53 self.stop()
70 self.stop()
54 # This restart event should leave the connection file in place so
71 # This restart event should leave the connection file in place so
55 # the ports are the same. Because this takes place below the
72 # the ports are the same. Because this takes place below the
56 # MappingKernelManager, the kernel_id will also remain the same.
73 # MappingKernelManager, the kernel_id will also remain the same.
74 self.log('KernelRestarter: restarting kernel')
57 self.kernel_manager.restart_kernel(now=True);
75 self.kernel_manager.restart_kernel(now=True);
58 self.start()
76 self.start()
59
77
60 def stop(self):
61 self.pc.stop()
62 self.pc = None
@@ -23,12 +23,15 b' import uuid'
23
23
24 import zmq
24 import zmq
25 from zmq.eventloop.zmqstream import ZMQStream
25 from zmq.eventloop.zmqstream import ZMQStream
26 from zmq.eventloop import ioloop
26
27
27 from IPython.config.configurable import LoggingConfigurable
28 from IPython.config.configurable import LoggingConfigurable
28 from IPython.utils.importstring import import_item
29 from IPython.utils.importstring import import_item
29 from IPython.utils.traitlets import (
30 from IPython.utils.traitlets import (
30 Instance, Dict, Unicode, Any, DottedObjectName,
31 Instance, Dict, Unicode, Any, DottedObjectName, Bool
31 )
32 )
33 # from IPython.kernel.kernelrestarter import KernelRestarter
34
32 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
33 # Classes
36 # Classes
34 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
@@ -61,7 +64,7 b' class MultiKernelManager(LoggingConfigurable):'
61 def _loop_default(self):
64 def _loop_default(self):
62 return ioloop.IOLoop.instance()
65 return ioloop.IOLoop.instance()
63
66
64 autorestart = Bool(True, config=True,
67 autorestart = Bool(False, config=True,
65 help="""Should we autorestart kernels that die."""
68 help="""Should we autorestart kernels that die."""
66 )
69 )
67
70
@@ -83,18 +86,29 b' class MultiKernelManager(LoggingConfigurable):'
83 def __contains__(self, kernel_id):
86 def __contains__(self, kernel_id):
84 return kernel_id in self._kernels
87 return kernel_id in self._kernels
85
88
86 def start_watching(self, kernel_id):
89 def start_restarter(self, kernel_id):
87 km = self.get_kernel(kernel_id):
90 km = self.get_kernel(kernel_id)
88 if self.autorestart:
91 if self.autorestart:
89 kr = KernelRestarter(
92 kr = self._restarters.get(kernel_id, None)
90 kernel_manager=km, loop=self.loop,
93 if kr is None:
91 config=self.config, log=self.log
94 kr = KernelRestarter(
92 )
95 kernel_manager=km, loop=self.loop,
96 config=self.config, log=self.log
97 )
98 self._restarters[kernel_id] = kr
93 kr.start()
99 kr.start()
94 self._restarters[kernel_id] = kr
95
100
96 def stop_watching(self, kernel_id):
101 def stop_restarter(self, kernel_id):
102 if self.autorestart:
103 kr = self._restarters.get(kernel_id, None)
104 if kr is not None:
105 kr.stop()
97
106
107 def clear_restarter(self, kernel_id):
108 if self.autorestart:
109 kr = self._restarters.pop(kernel_id, None)
110 if kr is not None:
111 kr.stop()
98
112
99 def start_kernel(self, **kwargs):
113 def start_kernel(self, **kwargs):
100 """Start a new kernel.
114 """Start a new kernel.
@@ -121,7 +135,7 b' class MultiKernelManager(LoggingConfigurable):'
121 # start just the shell channel, needed for graceful restart
135 # start just the shell channel, needed for graceful restart
122 km.start_channels(shell=True, iopub=False, stdin=False, hb=False)
136 km.start_channels(shell=True, iopub=False, stdin=False, hb=False)
123 self._kernels[kernel_id] = km
137 self._kernels[kernel_id] = km
124 self.start_watching(kernel_id)
138 self.start_restarter(kernel_id)
125 return kernel_id
139 return kernel_id
126
140
127 def shutdown_kernel(self, kernel_id, now=False):
141 def shutdown_kernel(self, kernel_id, now=False):
@@ -135,11 +149,11 b' class MultiKernelManager(LoggingConfigurable):'
135 Should the kernel be shutdown forcibly using a signal.
149 Should the kernel be shutdown forcibly using a signal.
136 """
150 """
137 k = self.get_kernel(kernel_id)
151 k = self.get_kernel(kernel_id)
138 self.stop_watching(kernel_id)
152 self.stop_restarter(kernel_id)
139 k.shutdown_kernel(now=now)
153 k.shutdown_kernel(now=now)
140 k.shell_channel.stop()
154 k.shell_channel.stop()
141 del self._kernels[kernel_id]
155 del self._kernels[kernel_id]
142 self.remove_watching(kernel_id)
156 self.clear_restarter(kernel_id)
143
157
144 def shutdown_all(self, now=False):
158 def shutdown_all(self, now=False):
145 """Shutdown all kernels."""
159 """Shutdown all kernels."""
@@ -178,9 +192,9 b' class MultiKernelManager(LoggingConfigurable):'
178 The id of the kernel to interrupt.
192 The id of the kernel to interrupt.
179 """
193 """
180 km = self.get_kernel(kernel_id)
194 km = self.get_kernel(kernel_id)
181 self.stop_watching()
195 self.stop_restarter(kernel_id)
182 km.restart_kernel()
196 km.restart_kernel()
183 self.start_watching()
197 self.start_restarter(kernel_id)
184
198
185 def is_alive(self, kernel_id):
199 def is_alive(self, kernel_id):
186 """Is the kernel alive.
200 """Is the kernel alive.
General Comments 0
You need to be logged in to leave comments. Login now