diff --git a/ipykernel/kernelapp.py b/ipykernel/kernelapp.py index 1f344f9ac..6e8517786 100644 --- a/ipykernel/kernelapp.py +++ b/ipykernel/kernelapp.py @@ -229,6 +229,8 @@ def init_connection_file(self): def init_sockets(self): # Create a context, a session, and the kernel sockets. self.log.info("Starting the kernel at pid: %i", os.getpid()) + # Note: don't call .instance(), otherwise forking the kernel does not work + # since the forked process will then use the same context context = zmq.Context() # Uncomment this to try closing the context. # atexit.register(context.term) @@ -510,6 +512,12 @@ def start(self): if not getattr(self.io_loop, '_fork_requested', False): keep_running = False else: + app_template = IPKernelApp(connection_file='forked.json') + app_template.write_connection_file() + import json + with open(app_template.abs_connection_file) as f: + conn = json.load(f) + pid = os.fork() self.io_loop._fork_requested = False # reset for parent AND child if pid == 0: @@ -569,13 +577,14 @@ def new_event_loop(self): # NOTE: we actually start a new kernel, but once this works # we can actually think about reusing the kernel object self.kernel_class.clear_instance() + self.initialize(argv=['-f', app_template.abs_connection_file, '--debug']) self.start() pass else: self.log.debug('Parent kernel will resume') # keep a reference, since the will set this to None post_fork_callback = self.io_loop._post_fork_callback - self.io_loop.add_callback(lambda: post_fork_callback(pid)) + self.io_loop.add_callback(lambda: post_fork_callback(pid, conn)) self.io_loop._post_fork_callback = None diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index 16926675d..cb4bca242 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -165,10 +165,10 @@ def fork(self, stream, ident, parent): # information up the callstack loop = ioloop.IOLoop.current() loop._fork_requested = True - def post_fork_callback(pid): + def post_fork_callback(pid, conn): # we might be able to pass back the port information/connection # info file here. This is just a proof of concept - reply_content = json_clean({'status': 'ok', 'fork_id': pid}) + reply_content = json_clean({'status': 'ok', 'fork_id': pid, 'conn': conn}) metadata = {} metadata = self.finish_metadata(parent, metadata, reply_content)