diff --git a/IPython/html/notebookapp.py b/IPython/html/notebookapp.py index 2069be1..a18860a 100644 --- a/IPython/html/notebookapp.py +++ b/IPython/html/notebookapp.py @@ -74,6 +74,7 @@ from IPython.kernel.zmq.session import default_secure, Session from IPython.nbformat.sign import NotebookNotary from IPython.utils.importstring import import_item from IPython.utils import submodule +from IPython.utils.process import check_pid from IPython.utils.traitlets import ( Dict, Unicode, Integer, List, Bool, Bytes, Instance, DottedObjectName, TraitError, @@ -841,6 +842,7 @@ class NotebookApp(BaseIPythonApplication): 'secure': bool(self.certfile), 'base_url': self.base_url, 'notebook_dir': os.path.abspath(self.notebook_dir), + 'pid': os.getpid() } def write_server_info_file(self): @@ -914,8 +916,17 @@ def list_running_servers(profile='default'): for file in os.listdir(pd.security_dir): if file.startswith('nbserver-'): with io.open(os.path.join(pd.security_dir, file), encoding='utf-8') as f: - yield json.load(f) + info = json.load(f) + # Simple check whether that process is really still running + if check_pid(info['pid']): + yield info + else: + # If the process has died, try to delete its info file + try: + os.unlink(file) + except OSError: + pass # TODO: This should warn or log or something #----------------------------------------------------------------------------- # Main entry point #----------------------------------------------------------------------------- diff --git a/IPython/parallel/apps/baseapp.py b/IPython/parallel/apps/baseapp.py index fa645fd..fc06304 100644 --- a/IPython/parallel/apps/baseapp.py +++ b/IPython/parallel/apps/baseapp.py @@ -36,6 +36,7 @@ from IPython.core.application import ( base_flags as base_ip_flags ) from IPython.utils.path import expand_path +from IPython.utils.process import check_pid from IPython.utils import py3compat from IPython.utils.py3compat import unicode_type @@ -249,28 +250,11 @@ class BaseParallelApplication(BaseIPythonApplication): raise PIDFileError('pid file not found: %s' % pid_file) def check_pid(self, pid): - if os.name == 'nt': - try: - import ctypes - # returns 0 if no such process (of ours) exists - # positive int otherwise - p = ctypes.windll.kernel32.OpenProcess(1,0,pid) - except Exception: - self.log.warn( - "Could not determine whether pid %i is running via `OpenProcess`. " - " Making the likely assumption that it is."%pid - ) - return True - return bool(p) - else: - try: - p = Popen(['ps','x'], stdout=PIPE, stderr=PIPE) - output,_ = p.communicate() - except OSError: - self.log.warn( - "Could not determine whether pid %i is running via `ps x`. " - " Making the likely assumption that it is."%pid - ) - return True - pids = list(map(int, re.findall(br'^\W*\d+', output, re.MULTILINE))) - return pid in pids + try: + return check_pid(pid) + except Exception: + self.log.warn( + "Could not determine whether pid %i is running. " + " Making the likely assumption that it is."%pid + ) + return True diff --git a/IPython/utils/_process_posix.py b/IPython/utils/_process_posix.py index 9c6054f..07be022 100644 --- a/IPython/utils/_process_posix.py +++ b/IPython/utils/_process_posix.py @@ -16,6 +16,8 @@ This file is only meant to be imported by process.py, not by end-users. from __future__ import print_function # Stdlib +import errno +import os import subprocess as sp import sys @@ -209,5 +211,15 @@ class ProcessHandler(object): # (ls is a good example) that makes them hard. system = ProcessHandler().system - - +def check_pid(pid): + try: + os.kill(pid, 0) + except OSError as err: + if err.errno == errno.ESRCH: + return False + elif err.errno == errno.EPERM: + # Don't have permission to signal the process - probably means it exists + return True + raise + else: + return True diff --git a/IPython/utils/_process_win32.py b/IPython/utils/_process_win32.py index 8b30c23..3ac59b2 100644 --- a/IPython/utils/_process_win32.py +++ b/IPython/utils/_process_win32.py @@ -185,3 +185,8 @@ try: return result except AttributeError: arg_split = py_arg_split + +def check_pid(pid): + # OpenProcess returns 0 if no such process (of ours) exists + # positive int otherwise + return bool(ctypes.windll.kernel32.OpenProcess(1,0,pid)) diff --git a/IPython/utils/process.py b/IPython/utils/process.py index a7a54ea..2a19945 100644 --- a/IPython/utils/process.py +++ b/IPython/utils/process.py @@ -21,11 +21,11 @@ import sys # Our own if sys.platform == 'win32': - from ._process_win32 import _find_cmd, system, getoutput, arg_split + from ._process_win32 import _find_cmd, system, getoutput, arg_split, check_pid elif sys.platform == 'cli': from ._process_cli import _find_cmd, system, getoutput, arg_split else: - from ._process_posix import _find_cmd, system, getoutput, arg_split + from ._process_posix import _find_cmd, system, getoutput, arg_split, check_pid from ._process_common import getoutputerror, get_output_error_code, process_handler from . import py3compat