Show More
@@ -246,12 +246,45 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 | """ | |||
|
255 | # FIXME: Shutdown does not work on Windows due to ZMQ errors! | |||
|
256 | if sys.platform == 'win32' and self.has_kernel: | |||
|
257 | return self._kill_kernel() | |||
251 | content = dict(restart=restart) |
|
258 | content = dict(restart=restart) | |
252 | msg = self.session.msg("shutdown_request", content=content) |
|
259 | msg = self.session.msg("shutdown_request", content=content) | |
253 | self.session.send(self._control_socket, msg) |
|
260 | self.session.send(self._control_socket, msg) | |
254 |
|
261 | |||
|
262 | def wait_shutdown(self, totaltime=1, interval=0.1): | |||
|
263 | """Wait for kernel shutdown, then kill process if it doesn't shutdown. | |||
|
264 | ||||
|
265 | This does not send shutdown requests - use :meth:`request_shutdown` | |||
|
266 | first. | |||
|
267 | """ | |||
|
268 | for i in range(int(totaltime/interval)): | |||
|
269 | if self.is_alive(): | |||
|
270 | time.sleep(interval) | |||
|
271 | else: | |||
|
272 | break | |||
|
273 | else: | |||
|
274 | # OK, we've waited long enough. | |||
|
275 | if self.has_kernel: | |||
|
276 | self._kill_kernel() | |||
|
277 | ||||
|
278 | def cleanup(self, restart=False): | |||
|
279 | """Clean up resources when the kernel is shut down""" | |||
|
280 | if not restart: | |||
|
281 | self.cleanup_connection_file() | |||
|
282 | self.cleanup_ipc_files() | |||
|
283 | else: | |||
|
284 | self.cleanup_ipc_files() | |||
|
285 | ||||
|
286 | self._close_control_socket() | |||
|
287 | ||||
255 | def shutdown_kernel(self, now=False, restart=False): |
|
288 | def shutdown_kernel(self, now=False, restart=False): | |
256 | """Attempts to the stop the kernel process cleanly. |
|
289 | """Attempts to the stop the kernel process cleanly. | |
257 |
|
290 | |||
@@ -273,32 +306,16 b' class KernelManager(LoggingConfigurable, ConnectionFileMixin):' | |||||
273 | # Stop monitoring for restarting while we shutdown. |
|
306 | # Stop monitoring for restarting while we shutdown. | |
274 | self.stop_restarter() |
|
307 | self.stop_restarter() | |
275 |
|
308 | |||
276 | # FIXME: Shutdown does not work on Windows due to ZMQ errors! |
|
309 | if now: | |
277 | if now or sys.platform == 'win32': |
|
310 | self._kill_kernel() | |
278 | if self.has_kernel: |
|
|||
279 | self._kill_kernel() |
|
|||
280 | else: |
|
311 | else: | |
|
312 | self.request_shutdown(restart=restart) | |||
281 | # Don't send any additional kernel kill messages immediately, to give |
|
313 | # Don't send any additional kernel kill messages immediately, to give | |
282 | # the kernel a chance to properly execute shutdown actions. Wait for at |
|
314 | # the kernel a chance to properly execute shutdown actions. Wait for at | |
283 | # most 1s, checking every 0.1s. |
|
315 | # most 1s, checking every 0.1s. | |
284 |
self. |
|
316 | self.wait_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 |
|
317 | |||
295 | if not restart: |
|
318 | self.cleanup(restart=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 |
|
319 | |||
303 | def restart_kernel(self, now=False, **kw): |
|
320 | def restart_kernel(self, now=False, **kw): | |
304 | """Restarts a kernel with the arguments that were used to launch it. |
|
321 | """Restarts a kernel with the arguments that were used to launch it. |
@@ -131,6 +131,20 b' class MultiKernelManager(LoggingConfigurable):' | |||||
131 | self.log.info("Kernel shutdown: %s" % kernel_id) |
|
131 | self.log.info("Kernel shutdown: %s" % kernel_id) | |
132 | self.remove_kernel(kernel_id) |
|
132 | self.remove_kernel(kernel_id) | |
133 |
|
133 | |||
|
134 | @kernel_method | |||
|
135 | def request_shutdown(self, kernel_id): | |||
|
136 | """Ask a kernel to shut down by its kernel uuid""" | |||
|
137 | ||||
|
138 | @kernel_method | |||
|
139 | def wait_shutdown(self, kernel_id): | |||
|
140 | """Wait for a kernel to finish shutting down, and kill it if it doesn't | |||
|
141 | """ | |||
|
142 | self.log.info("Kernel shutdown: %s" % kernel_id) | |||
|
143 | ||||
|
144 | @kernel_method | |||
|
145 | def cleanup(self, kernel_id): | |||
|
146 | """Clean up a kernel's resources""" | |||
|
147 | ||||
134 | def remove_kernel(self, kernel_id): |
|
148 | def remove_kernel(self, kernel_id): | |
135 | """remove a kernel from our mapping. |
|
149 | """remove a kernel from our mapping. | |
136 |
|
150 | |||
@@ -143,8 +157,12 b' class MultiKernelManager(LoggingConfigurable):' | |||||
143 |
|
157 | |||
144 | def shutdown_all(self, now=False): |
|
158 | def shutdown_all(self, now=False): | |
145 | """Shutdown all kernels.""" |
|
159 | """Shutdown all kernels.""" | |
146 |
|
|
160 | kids = self.list_kernel_ids() | |
147 | self.shutdown_kernel(kid, now=now) |
|
161 | for kid in kids: | |
|
162 | self.request_shutdown(kid) | |||
|
163 | for kid in kids: | |||
|
164 | self.wait_shutdown(kid) | |||
|
165 | self.cleanup(kid) | |||
148 |
|
166 | |||
149 | @kernel_method |
|
167 | @kernel_method | |
150 | def interrupt_kernel(self, kernel_id): |
|
168 | def interrupt_kernel(self, kernel_id): |
General Comments 0
You need to be logged in to leave comments.
Login now