Show More
@@ -11,11 +11,16 b' Things to do:' | |||
|
11 | 11 | * Implement event loop and poll version. |
|
12 | 12 | """ |
|
13 | 13 | |
|
14 | #----------------------------------------------------------------------------- | |
|
15 | # Imports | |
|
16 | #----------------------------------------------------------------------------- | |
|
17 | ||
|
14 | 18 | # Standard library imports. |
|
15 | 19 | import __builtin__ |
|
16 | 20 | from code import CommandCompiler |
|
17 | 21 | import os |
|
18 | 22 | import sys |
|
23 | from threading import Thread | |
|
19 | 24 | import time |
|
20 | 25 | import traceback |
|
21 | 26 | |
@@ -27,6 +32,9 b' from IPython.external.argparse import ArgumentParser' | |||
|
27 | 32 | from session import Session, Message, extract_header |
|
28 | 33 | from completer import KernelCompleter |
|
29 | 34 | |
|
35 | #----------------------------------------------------------------------------- | |
|
36 | # Kernel and stream classes | |
|
37 | #----------------------------------------------------------------------------- | |
|
30 | 38 | |
|
31 | 39 | class InStream(object): |
|
32 | 40 | """ A file like object that reads from a 0MQ XREQ socket.""" |
@@ -210,7 +218,6 b' class Kernel(object):' | |||
|
210 | 218 | self.history = [] |
|
211 | 219 | self.compiler = CommandCompiler() |
|
212 | 220 | self.completer = KernelCompleter(self.user_ns) |
|
213 | self.poll_ppid = False | |
|
214 | 221 | |
|
215 | 222 | # Build dict of handlers for message types |
|
216 | 223 | msg_types = [ 'execute_request', 'complete_request', |
@@ -325,10 +332,6 b' class Kernel(object):' | |||
|
325 | 332 | |
|
326 | 333 | def start(self): |
|
327 | 334 | while True: |
|
328 | if self.poll_ppid and os.getppid() == 1: | |
|
329 | print>>sys.__stderr__, "KILLED KERNEL. No parent process." | |
|
330 | os._exit(1) | |
|
331 | ||
|
332 | 335 | ident = self.reply_socket.recv() |
|
333 | 336 | assert self.reply_socket.rcvmore(), "Unexpected missing message part." |
|
334 | 337 | msg = self.reply_socket.recv_json() |
@@ -341,6 +344,34 b' class Kernel(object):' | |||
|
341 | 344 | else: |
|
342 | 345 | handler(ident, omsg) |
|
343 | 346 | |
|
347 | #----------------------------------------------------------------------------- | |
|
348 | # Kernel main and launch functions | |
|
349 | #----------------------------------------------------------------------------- | |
|
350 | ||
|
351 | class UnixPoller(Thread): | |
|
352 | ||
|
353 | def __init__(self): | |
|
354 | super(UnixPoller, self).__init__() | |
|
355 | self.daemon = True | |
|
356 | ||
|
357 | def run(self): | |
|
358 | while True: | |
|
359 | if os.getppid() == 1: | |
|
360 | os._exit(1) | |
|
361 | time.sleep(5.0) | |
|
362 | ||
|
363 | class WindowsPoller(Thread): | |
|
364 | ||
|
365 | def __init__(self, handle): | |
|
366 | super(WindowsPoller, self).__init__() | |
|
367 | self.daemon = True | |
|
368 | self.handle = handle | |
|
369 | ||
|
370 | def run(self): | |
|
371 | from _subprocess import WaitForSingleObject, WAIT_OBJECT_0, INFINITE | |
|
372 | result = WaitForSingleObject(self.handle, INFINITE) | |
|
373 | if result == WAIT_OBJECT_0: | |
|
374 | os._exit(1) | |
|
344 | 375 | |
|
345 | 376 | def bind_port(socket, ip, port): |
|
346 | 377 | """ Binds the specified ZMQ socket. If the port is less than zero, a random |
@@ -367,8 +398,13 b' def main():' | |||
|
367 | 398 | help='set the PUB channel port [default: random]') |
|
368 | 399 | parser.add_argument('--req', type=int, metavar='PORT', default=0, |
|
369 | 400 | help='set the REQ channel port [default: random]') |
|
370 | parser.add_argument('--require-parent', action='store_true', | |
|
371 | help='ensure that this process dies with its parent') | |
|
401 | if sys.platform == 'win32': | |
|
402 | parser.add_argument('--parent', type=int, metavar='HANDLE', | |
|
403 | default=0, help='kill this process if the process ' | |
|
404 | 'with HANDLE dies') | |
|
405 | else: | |
|
406 | parser.add_argument('--parent', action='store_true', | |
|
407 | help='kill this process if its parent dies') | |
|
372 | 408 | namespace = parser.parse_args() |
|
373 | 409 | |
|
374 | 410 | # Create a context, a session, and the kernel sockets. |
@@ -398,15 +434,18 b' def main():' | |||
|
398 | 434 | kernel = Kernel(session, reply_socket, pub_socket) |
|
399 | 435 | |
|
400 | 436 | # Configure this kernel/process to die on parent termination, if necessary. |
|
401 |
if namespace. |
|
|
437 | if namespace.parent: | |
|
402 | 438 | if sys.platform == 'linux2': |
|
403 | 439 | import ctypes, ctypes.util, signal |
|
404 | 440 | PR_SET_PDEATHSIG = 1 |
|
405 | 441 | libc = ctypes.CDLL(ctypes.util.find_library('c')) |
|
406 | 442 | libc.prctl(PR_SET_PDEATHSIG, signal.SIGKILL) |
|
407 | ||
|
408 | elif sys.platform != 'win32': | |
|
409 | kernel.poll_ppid = True | |
|
443 | elif sys.platform == 'win32': | |
|
444 | poller = WindowsPoller(namespace.parent) | |
|
445 | poller.start() | |
|
446 | else: | |
|
447 | poller = UnixPoller() | |
|
448 | poller.start() | |
|
410 | 449 | |
|
411 | 450 | # Start the kernel mainloop. |
|
412 | 451 | kernel.start() |
@@ -430,7 +469,7 b' def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False):' | |||
|
430 | 469 | If set, the kernel process is guaranteed to survive if this process |
|
431 | 470 | dies. If not set, an effort is made to ensure that the kernel is killed |
|
432 | 471 | when this process dies. Note that in this case it is still good practice |
|
433 |
to |
|
|
472 | to kill kernels manually before exiting. | |
|
434 | 473 | |
|
435 | 474 | Returns |
|
436 | 475 | ------- |
@@ -463,15 +502,22 b' def launch_kernel(xrep_port=0, pub_port=0, req_port=0, independent=False):' | |||
|
463 | 502 | command = 'from IPython.zmq.kernel import main; main()' |
|
464 | 503 | arguments = [ sys.executable, '-c', command, '--xrep', str(xrep_port), |
|
465 | 504 | '--pub', str(pub_port), '--req', str(req_port) ] |
|
466 | ||
|
467 | 505 | if independent: |
|
468 | 506 | if sys.platform == 'win32': |
|
469 | 507 | proc = Popen(['start', '/b'] + arguments, shell=True) |
|
470 | 508 | else: |
|
471 | 509 | proc = Popen(arguments, preexec_fn=lambda: os.setsid()) |
|
472 | ||
|
473 | 510 | else: |
|
474 | proc = Popen(arguments + ['--require-parent']) | |
|
511 | if sys.platform == 'win32': | |
|
512 | from _subprocess import DuplicateHandle, GetCurrentProcess, \ | |
|
513 | DUPLICATE_SAME_ACCESS | |
|
514 | pid = GetCurrentProcess() | |
|
515 | handle = DuplicateHandle(pid, pid, pid, 0, | |
|
516 | True, # Inheritable by new processes. | |
|
517 | DUPLICATE_SAME_ACCESS) | |
|
518 | proc = Popen(arguments + ['--parent', str(int(handle))]) | |
|
519 | else: | |
|
520 | proc = Popen(arguments + ['--parent']) | |
|
475 | 521 | |
|
476 | 522 | return proc, xrep_port, pub_port, req_port |
|
477 | 523 |
General Comments 0
You need to be logged in to leave comments.
Login now