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