Show More
@@ -246,12 +246,40 b' class KernelManager(LoggingConfigurable, ConnectionFileMixin):' | |||||
246 | self.start_restarter() |
|
246 | self.start_restarter() | |
247 | self._connect_control_socket() |
|
247 | self._connect_control_socket() | |
248 |
|
248 | |||
249 |
def |
|
249 | def request_shutdown(self, restart=False): | |
250 |
""" |
|
250 | """Send a shutdown request via control channel | |
|
251 | ||||
|
252 | On Windows, this just kills kernels instead, because the shutdown | |||
|
253 | messages don't work. | |||
|
254 | """ | |||
251 | content = dict(restart=restart) |
|
255 | content = dict(restart=restart) | |
252 | msg = self.session.msg("shutdown_request", content=content) |
|
256 | msg = self.session.msg("shutdown_request", content=content) | |
253 | self.session.send(self._control_socket, msg) |
|
257 | self.session.send(self._control_socket, msg) | |
254 |
|
258 | |||
|
259 | def finish_shutdown(self, waittime=1, pollinterval=0.1): | |||
|
260 | """Wait for kernel shutdown, then kill process if it doesn't shutdown. | |||
|
261 | ||||
|
262 | This does not send shutdown requests - use :meth:`request_shutdown` | |||
|
263 | first. | |||
|
264 | """ | |||
|
265 | for i in range(int(waittime/pollinterval)): | |||
|
266 | if self.is_alive(): | |||
|
267 | time.sleep(pollinterval) | |||
|
268 | else: | |||
|
269 | break | |||
|
270 | else: | |||
|
271 | # OK, we've waited long enough. | |||
|
272 | if self.has_kernel: | |||
|
273 | self._kill_kernel() | |||
|
274 | ||||
|
275 | def cleanup(self, connection_file=True): | |||
|
276 | """Clean up resources when the kernel is shut down""" | |||
|
277 | if connection_file: | |||
|
278 | self.cleanup_connection_file() | |||
|
279 | ||||
|
280 | self.cleanup_ipc_files() | |||
|
281 | self._close_control_socket() | |||
|
282 | ||||
255 | def shutdown_kernel(self, now=False, restart=False): |
|
283 | def shutdown_kernel(self, now=False, restart=False): | |
256 | """Attempts to the stop the kernel process cleanly. |
|
284 | """Attempts to the stop the kernel process cleanly. | |
257 |
|
285 | |||
@@ -273,32 +301,16 b' class KernelManager(LoggingConfigurable, ConnectionFileMixin):' | |||||
273 | # Stop monitoring for restarting while we shutdown. |
|
301 | # Stop monitoring for restarting while we shutdown. | |
274 | self.stop_restarter() |
|
302 | self.stop_restarter() | |
275 |
|
303 | |||
276 | # FIXME: Shutdown does not work on Windows due to ZMQ errors! |
|
304 | if now: | |
277 | if now or sys.platform == 'win32': |
|
305 | self._kill_kernel() | |
278 | if self.has_kernel: |
|
|||
279 | self._kill_kernel() |
|
|||
280 | else: |
|
306 | else: | |
|
307 | self.request_shutdown(restart=restart) | |||
281 | # Don't send any additional kernel kill messages immediately, to give |
|
308 | # Don't send any additional kernel kill messages immediately, to give | |
282 | # the kernel a chance to properly execute shutdown actions. Wait for at |
|
309 | # the kernel a chance to properly execute shutdown actions. Wait for at | |
283 | # most 1s, checking every 0.1s. |
|
310 | # most 1s, checking every 0.1s. | |
284 |
self. |
|
311 | self.finish_shutdown() | |
285 | for i in range(10): |
|
|||
286 | if self.is_alive(): |
|
|||
287 | time.sleep(0.1) |
|
|||
288 | else: |
|
|||
289 | break |
|
|||
290 | else: |
|
|||
291 | # OK, we've waited long enough. |
|
|||
292 | if self.has_kernel: |
|
|||
293 | self._kill_kernel() |
|
|||
294 |
|
312 | |||
295 | if not restart: |
|
313 | self.cleanup(connection_file=not restart) | |
296 | self.cleanup_connection_file() |
|
|||
297 | self.cleanup_ipc_files() |
|
|||
298 | else: |
|
|||
299 | self.cleanup_ipc_files() |
|
|||
300 |
|
||||
301 | self._close_control_socket() |
|
|||
302 |
|
314 | |||
303 | def restart_kernel(self, now=False, **kw): |
|
315 | def restart_kernel(self, now=False, **kw): | |
304 | """Restarts a kernel with the arguments that were used to launch it. |
|
316 | """Restarts a kernel with the arguments that were used to launch it. | |
@@ -331,11 +343,6 b' class KernelManager(LoggingConfigurable, ConnectionFileMixin):' | |||||
331 | self._launch_args.update(kw) |
|
343 | self._launch_args.update(kw) | |
332 | self.start_kernel(**self._launch_args) |
|
344 | self.start_kernel(**self._launch_args) | |
333 |
|
345 | |||
334 | # FIXME: Messages get dropped in Windows due to probable ZMQ bug |
|
|||
335 | # unless there is some delay here. |
|
|||
336 | if sys.platform == 'win32': |
|
|||
337 | time.sleep(0.2) |
|
|||
338 |
|
||||
339 | @property |
|
346 | @property | |
340 | def has_kernel(self): |
|
347 | def has_kernel(self): | |
341 | """Has a kernel been started that we are managing.""" |
|
348 | """Has a kernel been started that we are managing.""" |
@@ -118,7 +118,7 b' class MultiKernelManager(LoggingConfigurable):' | |||||
118 | return kernel_id |
|
118 | return kernel_id | |
119 |
|
119 | |||
120 | @kernel_method |
|
120 | @kernel_method | |
121 | def shutdown_kernel(self, kernel_id, now=False): |
|
121 | def shutdown_kernel(self, kernel_id, now=False, restart=False): | |
122 | """Shutdown a kernel by its kernel uuid. |
|
122 | """Shutdown a kernel by its kernel uuid. | |
123 |
|
123 | |||
124 | Parameters |
|
124 | Parameters | |
@@ -127,10 +127,26 b' class MultiKernelManager(LoggingConfigurable):' | |||||
127 | The id of the kernel to shutdown. |
|
127 | The id of the kernel to shutdown. | |
128 | now : bool |
|
128 | now : bool | |
129 | Should the kernel be shutdown forcibly using a signal. |
|
129 | Should the kernel be shutdown forcibly using a signal. | |
|
130 | restart : bool | |||
|
131 | Will the kernel be restarted? | |||
130 | """ |
|
132 | """ | |
131 | self.log.info("Kernel shutdown: %s" % kernel_id) |
|
133 | self.log.info("Kernel shutdown: %s" % kernel_id) | |
132 | self.remove_kernel(kernel_id) |
|
134 | self.remove_kernel(kernel_id) | |
133 |
|
135 | |||
|
136 | @kernel_method | |||
|
137 | def request_shutdown(self, kernel_id, restart=False): | |||
|
138 | """Ask a kernel to shut down by its kernel uuid""" | |||
|
139 | ||||
|
140 | @kernel_method | |||
|
141 | def finish_shutdown(self, kernel_id, waittime=1, pollinterval=0.1): | |||
|
142 | """Wait for a kernel to finish shutting down, and kill it if it doesn't | |||
|
143 | """ | |||
|
144 | self.log.info("Kernel shutdown: %s" % kernel_id) | |||
|
145 | ||||
|
146 | @kernel_method | |||
|
147 | def cleanup(self, kernel_id, connection_file=True): | |||
|
148 | """Clean up a kernel's resources""" | |||
|
149 | ||||
134 | def remove_kernel(self, kernel_id): |
|
150 | def remove_kernel(self, kernel_id): | |
135 | """remove a kernel from our mapping. |
|
151 | """remove a kernel from our mapping. | |
136 |
|
152 | |||
@@ -143,8 +159,12 b' class MultiKernelManager(LoggingConfigurable):' | |||||
143 |
|
159 | |||
144 | def shutdown_all(self, now=False): |
|
160 | def shutdown_all(self, now=False): | |
145 | """Shutdown all kernels.""" |
|
161 | """Shutdown all kernels.""" | |
146 |
|
|
162 | kids = self.list_kernel_ids() | |
147 | self.shutdown_kernel(kid, now=now) |
|
163 | for kid in kids: | |
|
164 | self.request_shutdown(kid) | |||
|
165 | for kid in kids: | |||
|
166 | self.finish_shutdown(kid) | |||
|
167 | self.cleanup(kid) | |||
148 |
|
168 | |||
149 | @kernel_method |
|
169 | @kernel_method | |
150 | def interrupt_kernel(self, kernel_id): |
|
170 | def interrupt_kernel(self, kernel_id): |
General Comments 0
You need to be logged in to leave comments.
Login now