def fork_kernel(self, config, pipe, resource_limits): """ A function to be set as the target for the new kernel processes forked in ForkingKernelManager.start_kernel. This method forks and initializes a new kernel, uses the update_function to update the kernel's namespace, sets resource limits for the kernel, and sends kernel connection information through the Pipe object. :arg traitlets.config.loader config: kernel configuration :arg multiprocessing.Pipe pipe: a multiprocessing connection object which will send kernel ip, session, and port information to the other side :arg dict resource_limits: a dict with keys resource.RLIMIT_* (see config_default documentation for explanation of valid options) and values of the limit for the given resource to be set in the kernel process """ os.setpgrp() logger = kernel_logger.getChild(str(uuid.uuid4())[:4]) logger.debug("kernel forked; now starting and configuring") try: ka = IPKernelApp.instance(config=config, ip=config["ip"]) ka.log.propagate = True ka.log_level = logger.level from namespace import InstrumentedNamespace ka.user_ns = InstrumentedNamespace() ka.initialize([]) except: logger.exception("Error initializing IPython kernel") # FIXME: What's the point in proceeding after?! try: if self.update_function is not None: self.update_function(ka) except: logger.exception("Error configuring up kernel") logger.debug("finished updating") for r, limit in resource_limits.iteritems(): resource.setrlimit(getattr(resource, r), (limit, limit)) pipe.send({"ip": ka.ip, "key": ka.session.key, "shell_port": ka.shell_port, "stdin_port": ka.stdin_port, "hb_port": ka.hb_port, "iopub_port": ka.iopub_port}) pipe.close() # The following line will erase JSON connection file with ports and # other numbers. Since we do not reuse the kernels, we don't really need # these files. And new kernels set atexit hook to delete the file, but # it does not get called, perhaps because kernels are stopped by system # signals. The result is accumulation of files leading to disk quota # issues AND attempts to use stale files to connect to non-existing # kernels that eventually crash the server. TODO: figure out a better # fix, perhaps kernels have to be stopped in a more gentle fashion? ka.cleanup_connection_file() # In order to show the correct code line when a (deprecation) warning # is triggered, we change the main module name and save user code to # a file with the same name. import sys sys.argv = ['sagemathcell.py'] old_execute = ka.kernel.do_execute import codecs def new_execute(code, *args, **kwds): with codecs.open('sagemathcell.py', 'w', encoding='utf-8') as f: f.write(code) return old_execute(code, *args, **kwds) ka.kernel.do_execute = new_execute ka.start()
def fork_kernel(self, config, pipe, resource_limits): """ A function to be set as the target for the new kernel processes forked in ForkingKernelManager.start_kernel. This method forks and initializes a new kernel, uses the update_function to update the kernel's namespace, sets resource limits for the kernel, and sends kernel connection information through the Pipe object. :arg IPython.config.loader config: kernel configuration :arg multiprocessing.Pipe pipe: a multiprocessing connection object which will send kernel ip, session, and port information to the other side :arg dict resource_limits: a dict with keys resource.RLIMIT_* (see config_default documentation for explanation of valid options) and values of the limit for the given resource to be set in the kernel process """ os.setpgrp() logger = kernel_logger.getChild(str(uuid.uuid4())[:4]) logger.debug("kernel forked; now starting and configuring") try: ka = IPKernelApp.instance(config=config, ip=config["ip"]) from namespace import InstrumentedNamespace ka.user_ns = InstrumentedNamespace() # The following line on UNIX systems (and we are unlikely to run on # Windows) will lead to creation of a 1-second poller that will kill # this process as soon as its parent dies. More importanly, it will # prevent from execution the following if block: # https://github.com/ipython/ipython/blob/rel-2.1.0/IPython/kernel/zmq/kernelapp.py#L348 # which probably was filling some output buffer and used to severely # limit the number of computations possible without restarting the # server. TODO: figure out a better fix or confirm this is the one! ka.parent_handle = True ka.initialize([]) except: logger.exception("Error initializing IPython kernel") # FIXME: What's the point in proceeding after?! try: if self.update_function is not None: self.update_function(ka) except: logger.exception("Error configuring up kernel") logger.debug("finished updating") for r, limit in resource_limits.iteritems(): resource.setrlimit(getattr(resource, r), (limit, limit)) pipe.send({ "ip": ka.ip, "key": ka.session.key, "shell_port": ka.shell_port, "stdin_port": ka.stdin_port, "hb_port": ka.hb_port, "iopub_port": ka.iopub_port }) pipe.close() # The following line will erase JSON connection file with ports and # other numbers. Since we do not reuse the kernels, we don't really need # these files. And new kernels set atexit hook to delete the file, but # it does not get called, perhaps because kernels are stopped by system # signals. The result is accumulation of files leading to disk quota # issues AND attempts to use stale files to connect to non-existing # kernels that eventually crash the server. TODO: figure out a better # fix, perhaps kernels have to be stopped in a more gentle fashion? ka.cleanup_connection_file() ka.start()
def fork_kernel(self, config, pipe, resource_limits): """ A function to be set as the target for the new kernel processes forked in ForkingKernelManager.start_kernel. This method forks and initializes a new kernel, uses the update_function to update the kernel's namespace, sets resource limits for the kernel, and sends kernel connection information through the Pipe object. :arg IPython.config.loader config: kernel configuration :arg multiprocessing.Pipe pipe: a multiprocessing connection object which will send kernel ip, session, and port information to the other side :arg dict resource_limits: a dict with keys resource.RLIMIT_* (see config_default documentation for explanation of valid options) and values of the limit for the given resource to be set in the kernel process """ os.setpgrp() logger = kernel_logger.getChild(str(uuid.uuid4())[:4]) logger.debug("kernel forked; now starting and configuring") try: ka = IPKernelApp.instance(config=config, ip=config["ip"]) from namespace import InstrumentedNamespace ka.user_ns = InstrumentedNamespace() # The following line on UNIX systems (and we are unlikely to run on # Windows) will lead to creation of a 1-second poller that will kill # this process as soon as its parent dies. More importanly, it will # prevent from execution the following if block: # https://github.com/ipython/ipython/blob/rel-2.1.0/IPython/kernel/zmq/kernelapp.py#L348 # which probably was filling some output buffer and used to severely # limit the number of computations possible without restarting the # server. TODO: figure out a better fix or confirm this is the one! ka.parent_handle = True ka.initialize([]) except: logger.exception("Error initializing IPython kernel") # FIXME: What's the point in proceeding after?! try: if self.update_function is not None: self.update_function(ka) except: logger.exception("Error configuring up kernel") logger.debug("finished updating") for r, limit in resource_limits.iteritems(): resource.setrlimit(getattr(resource, r), (limit, limit)) pipe.send({"ip": ka.ip, "key": ka.session.key, "shell_port": ka.shell_port, "stdin_port": ka.stdin_port, "hb_port": ka.hb_port, "iopub_port": ka.iopub_port}) pipe.close() # The following line will erase JSON connection file with ports and # other numbers. Since we do not reuse the kernels, we don't really need # these files. And new kernels set atexit hook to delete the file, but # it does not get called, perhaps because kernels are stopped by system # signals. The result is accumulation of files leading to disk quota # issues AND attempts to use stale files to connect to non-existing # kernels that eventually crash the server. TODO: figure out a better # fix, perhaps kernels have to be stopped in a more gentle fashion? ka.cleanup_connection_file() ka.start()
def fork_kernel(self, config, pipe, resource_limits): """The target for new processes in ForkingKernelManager.start_kernel. This method forks and initializes a new kernel, uses the update_function to update the kernel's namespace, sets resource limits for the kernel, and sends kernel connection information through the Pipe object. :arg traitlets.config.loader config: kernel configuration :arg multiprocessing.Pipe pipe: a pipe for sending kernel ip, session, and port information to the other side :arg dict resource_limits: a dictionary with keys resource.RLIMIT_* (see config_default documentation for explanation of valid options) """ os.setpgrp() logger = kernel_logger.getChild(str(uuid.uuid4())[:4]) logger.debug("kernel forked; now starting and configuring") try: ka = IPKernelApp.instance(config=config, ip=config["ip"]) ka.log.propagate = True ka.log_level = logger.level from namespace import InstrumentedNamespace ka.user_ns = InstrumentedNamespace() ka.initialize([]) except: logger.exception("error initializing IPython kernel") raise KernelError("error initializing IPython kernel") try: if self.update_function is not None: self.update_function(ka) except: logger.exception("error configuring up kernel") raise KernelError("error configuring up kernel") logger.debug("finished updating") for r, limit in resource_limits.iteritems(): resource.setrlimit(getattr(resource, r), (limit, limit)) pipe.send({ "ip": ka.ip, "key": ka.session.key, "shell_port": ka.shell_port, "stdin_port": ka.stdin_port, "hb_port": ka.hb_port, "iopub_port": ka.iopub_port }) pipe.close() # The following line will erase JSON connection file with ports and # other numbers. Since we do not reuse the kernels, we don't really need # these files. And new kernels set atexit hook to delete the file, but # it does not get called, perhaps because kernels are stopped by system # signals. The result is accumulation of files leading to disk quota # issues AND attempts to use stale files to connect to non-existing # kernels that eventually crash the server. TODO: figure out a better # fix, perhaps kernels have to be stopped in a more gentle fashion? ka.cleanup_connection_file() # In order to show the correct code line when a (deprecation) warning # is triggered, we change the main module name and save user code to # a file with the same name. import sys sys.argv = ['sagemathcell.py'] old_execute = ka.kernel.do_execute import codecs def new_execute(code, *args, **kwds): with codecs.open('sagemathcell.py', 'w', encoding='utf-8') as f: f.write(code) return old_execute(code, *args, **kwds) ka.kernel.do_execute = new_execute ka.start()