##// END OF EJS Templates
improve cleanup of connection files...
MinRK -
Show More
@@ -21,6 +21,7 b' Authors:'
21 21 #-----------------------------------------------------------------------------
22 22
23 23 # stdlib imports
24 import atexit
24 25 import json
25 26 import os
26 27 import signal
@@ -234,6 +235,9 b' class IPythonMixinConsoleApp(Configurable):'
234 235 argument does not match an existing file, it will be interpreted as a
235 236 fileglob, and the matching file in the current profile's security dir
236 237 with the latest access time will be used.
238
239 After this method is called, self.connection_file contains the *full path*
240 to the connection file, never just its name.
237 241 """
238 242 if self.existing:
239 243 try:
@@ -243,6 +247,20 b' class IPythonMixinConsoleApp(Configurable):'
243 247 self.exit(1)
244 248 self.log.info("Connecting to existing kernel: %s" % cf)
245 249 self.connection_file = cf
250 else:
251 # not existing, check if we are going to write the file
252 # and ensure that self.connection_file is a full path, not just the shortname
253 try:
254 cf = find_connection_file(self.connection_file)
255 except Exception:
256 # file might not exist
257 if self.connection_file == os.path.basename(self.connection_file):
258 # just shortname, put it in security dir
259 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
260 else:
261 cf = self.connection_file
262 self.connection_file = cf
263
246 264 # should load_connection_file only be used for existing?
247 265 # as it is now, this allows reusing ports if an existing
248 266 # file is requested
@@ -315,21 +333,21 b' class IPythonMixinConsoleApp(Configurable):'
315 333 self.log.critical("--existing %s" % self.connection_file)
316 334
317 335 def _new_connection_file(self):
318 return os.path.join(self.profile_dir.security_dir, 'kernel-%s.json' % uuid.uuid4())
336 cf = ''
337 while not cf:
338 # we don't need a 128b id to distinguish kernels, use more readable
339 # 48b node segment (12 hex chars). Users running more than 32k simultaneous
340 # kernels can subclass.
341 ident = str(uuid.uuid4()).split('-')[-1]
342 cf = os.path.join(self.profile_dir.security_dir, 'kernel-%s.json' % ident)
343 # only keep if it's actually new. Protect against unlikely collision
344 # in 48b random search space
345 cf = cf if not os.path.exists(cf) else ''
346 return cf
319 347
320 348 def init_kernel_manager(self):
321 349 # Don't let Qt or ZMQ swallow KeyboardInterupts.
322 350 signal.signal(signal.SIGINT, signal.SIG_DFL)
323 sec = self.profile_dir.security_dir
324 try:
325 cf = filefind(self.connection_file, ['.', sec])
326 except IOError:
327 # file might not exist
328 if self.connection_file == os.path.basename(self.connection_file):
329 # just shortname, put it in security dir
330 cf = os.path.join(sec, self.connection_file)
331 else:
332 cf = self.connection_file
333 351
334 352 # Create a KernelManager and start a kernel.
335 353 self.kernel_manager = self.kernel_manager_class(
@@ -338,7 +356,7 b' class IPythonMixinConsoleApp(Configurable):'
338 356 iopub_port=self.iopub_port,
339 357 stdin_port=self.stdin_port,
340 358 hb_port=self.hb_port,
341 connection_file=cf,
359 connection_file=self.connection_file,
342 360 config=self.config,
343 361 )
344 362 # start the kernel
@@ -349,6 +367,7 b' class IPythonMixinConsoleApp(Configurable):'
349 367 elif self.sshserver:
350 368 # ssh, write new connection file
351 369 self.kernel_manager.write_connection_file()
370 atexit.register(self.kernel_manager.cleanup_connection_file)
352 371 self.kernel_manager.start_channels()
353 372
354 373
@@ -27,7 +27,7 b' import sys'
27 27 import uuid
28 28
29 29 # System library imports
30 from IPython.external.qt import QtGui
30 from IPython.external.qt import QtCore, QtGui
31 31
32 32 # Local imports
33 33 from IPython.config.application import boolean_flag, catch_config_error
@@ -298,12 +298,26 b' class IPythonQtConsoleApp(BaseIPythonApplication, IPythonMixinConsoleApp):'
298 298 else:
299 299 raise IOError("Stylesheet %r not found."%self.stylesheet)
300 300
301 def init_signal(self):
302 """allow clean shutdown on sigint"""
303 signal.signal(signal.SIGINT, lambda sig, frame: self.exit(-2))
304 # need a timer, so that QApplication doesn't block until a real
305 # Qt event fires (can require mouse movement)
306 # timer trick from http://stackoverflow.com/q/4938723/938949
307 timer = QtCore.QTimer()
308 # Let the interpreter run each 200 ms:
309 timer.timeout.connect(lambda: None)
310 timer.start(200)
311 # hold onto ref, so the timer doesn't get cleaned up
312 self._sigint_timer = timer
313
301 314 @catch_config_error
302 315 def initialize(self, argv=None):
303 316 super(IPythonQtConsoleApp, self).initialize(argv)
304 317 IPythonMixinConsoleApp.initialize(self,argv)
305 318 self.init_qt_elements()
306 319 self.init_colors()
320 self.init_signal()
307 321
308 322 def start(self):
309 323
@@ -639,14 +639,8 b' class KernelManager(HasTraits):'
639 639 self.session = Session(config=self.config)
640 640
641 641 def __del__(self):
642 if self._connection_file_written:
643 # cleanup connection files on full shutdown of kernel we started
644 self._connection_file_written = False
645 try:
646 os.remove(self.connection_file)
647 except IOError:
648 pass
649
642 self.cleanup_connection_file()
643
650 644
651 645 #--------------------------------------------------------------------------
652 646 # Channel management methods:
@@ -694,6 +688,19 b' class KernelManager(HasTraits):'
694 688 # Kernel process management methods:
695 689 #--------------------------------------------------------------------------
696 690
691 def cleanup_connection_file(self):
692 """cleanup connection file *if we wrote it*
693
694 Will not raise if the connection file was already removed somehow.
695 """
696 if self._connection_file_written:
697 # cleanup connection files on full shutdown of kernel we started
698 self._connection_file_written = False
699 try:
700 os.remove(self.connection_file)
701 except OSError:
702 pass
703
697 704 def load_connection_file(self):
698 705 """load connection info from JSON dict in self.connection_file"""
699 706 with open(self.connection_file) as f:
General Comments 0
You need to be logged in to leave comments. Login now