Python errno.ESRCH Examples

The following are 30 code examples of errno.ESRCH(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module errno , or try the search function .
Example #1
Source File: _pswindows.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def memory_maps(self):
        try:
            raw = cext.proc_memory_maps(self.pid)
        except OSError as err:
            # XXX - can't use wrap_exceptions decorator as we're
            # returning a generator; probably needs refactoring.
            if err.errno in ACCESS_DENIED_ERRSET:
                raise AccessDenied(self.pid, self._name)
            if err.errno == errno.ESRCH:
                raise NoSuchProcess(self.pid, self._name)
            raise
        else:
            for addr, perm, path, rss in raw:
                path = convert_dos_path(path)
                if not PY3:
                    assert isinstance(path, unicode), type(path)
                    path = py2_strencode(path)
                addr = hex(addr)
                yield (addr, perm, path, rss) 
Example #2
Source File: _pslinux.py    From teleport with Apache License 2.0 6 votes vote down vote up
def ppid_map():
    """Obtain a {pid: ppid, ...} dict for all running processes in
    one shot. Used to speed up Process.children().
    """
    ret = {}
    procfs_path = get_procfs_path()
    for pid in pids():
        try:
            with open_binary("%s/%s/stat" % (procfs_path, pid)) as f:
                data = f.read()
        except EnvironmentError as err:
            # Note: we should be able to access /stat for all processes
            # aka it's unlikely we'll bump into EPERM, which is good.
            if err.errno not in (errno.ENOENT, errno.ESRCH):
                raise
        else:
            rpar = data.rfind(b')')
            dset = data[rpar + 2:].split()
            ppid = int(dset[1])
            ret[pid] = ppid
    return ret 
Example #3
Source File: _psosx.py    From teleport with Apache License 2.0 6 votes vote down vote up
def catch_zombie(proc):
    """There are some poor C APIs which incorrectly raise ESRCH when
    the process is still alive or it's a zombie, or even RuntimeError
    (those who don't set errno). This is here in order to solve:
    https://github.com/giampaolo/psutil/issues/1044
    """
    try:
        yield
    except (OSError, RuntimeError) as err:
        if isinstance(err, RuntimeError) or err.errno == errno.ESRCH:
            try:
                # status() is not supposed to lie and correctly detect
                # zombies so if it raises ESRCH it's true.
                status = proc.status()
            except NoSuchProcess:
                raise err
            else:
                if status == _common.STATUS_ZOMBIE:
                    raise ZombieProcess(proc.pid, proc._name, proc._ppid)
                else:
                    raise AccessDenied(proc.pid, proc._name)
        else:
            raise 
Example #4
Source File: kernel.py    From rift-python with Apache License 2.0 6 votes vote down vote up
def del_route(self, prefix):
        if not self.platform_supported or self._simulated_interfaces:
            return False
        if self._table_nr == -1:
            return False
        dst = packet_common.ip_prefix_str(prefix)
        try:
            self.ipr.route('del', table=self._table_nr, dst=dst, proto=RTPROT_RIFT,
                           priority=RTPRIORITY_RIFT)
        except pyroute2.netlink.exceptions.NetlinkError as err:
            if err.code != errno.ESRCH:  # It is not an error to delete a non-existing route
                self.error("Netlink error \"%s\" deleting route to %s", err, dst)
            return False
        except OSError as err:
            self.error("OS error \"%s\" deleting route to %s", err, dst)
            return False
        else:
            self.debug("Delete route to %s", prefix)
            return True 
Example #5
Source File: _psosx.py    From teleport with Apache License 2.0 6 votes vote down vote up
def wrap_exceptions(fun):
    """Decorator which translates bare OSError exceptions into
    NoSuchProcess and AccessDenied.
    """
    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except OSError as err:
            if err.errno == errno.ESRCH:
                raise NoSuchProcess(self.pid, self._name)
            if err.errno in (errno.EPERM, errno.EACCES):
                raise AccessDenied(self.pid, self._name)
            raise
        except cext.ZombieProcessError:
            raise ZombieProcess(self.pid, self._name, self._ppid)
    return wrapper 
Example #6
Source File: _pslinux.py    From teleport with Apache License 2.0 6 votes vote down vote up
def exe(self):
        try:
            return readlink("%s/%s/exe" % (self._procfs_path, self.pid))
        except OSError as err:
            if err.errno in (errno.ENOENT, errno.ESRCH):
                # no such file error; might be raised also if the
                # path actually exists for system processes with
                # low pids (about 0-20)
                if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)):
                    return ""
                else:
                    if not pid_exists(self.pid):
                        raise NoSuchProcess(self.pid, self._name)
                    else:
                        raise ZombieProcess(self.pid, self._name, self._ppid)
            if err.errno in (errno.EPERM, errno.EACCES):
                raise AccessDenied(self.pid, self._name)
            raise 
Example #7
Source File: _pslinux.py    From teleport with Apache License 2.0 6 votes vote down vote up
def wrap_exceptions(fun):
    """Decorator which translates bare OSError and IOError exceptions
    into NoSuchProcess and AccessDenied.
    """
    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except EnvironmentError as err:
            if err.errno in (errno.EPERM, errno.EACCES):
                raise AccessDenied(self.pid, self._name)
            # ESRCH (no such process) can be raised on read() if
            # process is gone in the meantime.
            if err.errno == errno.ESRCH:
                raise NoSuchProcess(self.pid, self._name)
            # ENOENT (no such file or directory) can be raised on open().
            if err.errno == errno.ENOENT and not os.path.exists("%s/%s" % (
                    self._procfs_path, self.pid)):
                raise NoSuchProcess(self.pid, self._name)
            # Note: zombies will keep existing under /proc until they're
            # gone so there's no way to distinguish them in here.
            raise
    return wrapper 
Example #8
Source File: _psbsd.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def wrap_exceptions_procfs(inst):
    """Same as above, for routines relying on reading /proc fs."""
    try:
        yield
    except EnvironmentError as err:
        # ENOENT (no such file or directory) gets raised on open().
        # ESRCH (no such process) can get raised on read() if
        # process is gone in meantime.
        if err.errno in (errno.ENOENT, errno.ESRCH):
            if not pid_exists(inst.pid):
                raise NoSuchProcess(inst.pid, inst._name)
            else:
                raise ZombieProcess(inst.pid, inst._name, inst._ppid)
        if err.errno in (errno.EPERM, errno.EACCES):
            raise AccessDenied(inst.pid, inst._name)
        raise 
Example #9
Source File: util.py    From benchexec with Apache License 2.0 6 votes vote down vote up
def kill_process(pid, sig=None):
    """Try to send signal to given process."""
    if sig is None:
        sig = signal.SIGKILL  # set default lazily, otherwise importing fails on Windows
    try:
        os.kill(pid, sig)
    except OSError as e:
        if e.errno == errno.ESRCH:
            # process itself returned and exited before killing
            logging.debug(
                "Failure %s while killing process %s with signal %s: %s",
                e.errno,
                pid,
                sig,
                e.strerror,
            )
        else:
            logging.warning(
                "Failure %s while killing process %s with signal %s: %s",
                e.errno,
                pid,
                sig,
                e.strerror,
            ) 
Example #10
Source File: integration_server.py    From gnsq with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def __exit__(self, exc_type, exc_value, traceback):
        try:
            self.child.terminate()
        except OSError as error:
            if error.errno == errno.ESRCH:
                return
            raise

        while True:
            line = self.child.stderr.readline()
            if not line:
                break
            sys.stderr.write(line)

        self.child.wait()
        shutil.rmtree(self.data_path) 
Example #11
Source File: arbiter.py    From jbox with MIT License 6 votes vote down vote up
def kill_worker(self, pid, sig):
        """\
        Kill a worker

        :attr pid: int, worker pid
        :attr sig: `signal.SIG*` value
         """
        try:
            os.kill(pid, sig)
        except OSError as e:
            if e.errno == errno.ESRCH:
                try:
                    worker = self.WORKERS.pop(pid)
                    worker.tmp.close()
                    self.cfg.worker_exit(self, worker)
                    return
                except (KeyError, OSError):
                    return
            raise 
Example #12
Source File: _pslinux.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def get_all_inodes(self):
        inodes = {}
        for pid in pids():
            try:
                inodes.update(self.get_proc_inodes(pid))
            except OSError as err:
                # os.listdir() is gonna raise a lot of access denied
                # exceptions in case of unprivileged user; that's fine
                # as we'll just end up returning a connection with PID
                # and fd set to None anyway.
                # Both netstat -an and lsof does the same so it's
                # unlikely we can do any better.
                # ENOENT just means a PID disappeared on us.
                if err.errno not in (
                        errno.ENOENT, errno.ESRCH, errno.EPERM, errno.EACCES):
                    raise
        return inodes 
Example #13
Source File: _pslinux.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def ppid_map():
    """Obtain a {pid: ppid, ...} dict for all running processes in
    one shot. Used to speed up Process.children().
    """
    ret = {}
    procfs_path = get_procfs_path()
    for pid in pids():
        try:
            with open_binary("%s/%s/stat" % (procfs_path, pid)) as f:
                data = f.read()
        except EnvironmentError as err:
            # Note: we should be able to access /stat for all processes
            # aka it's unlikely we'll bump into EPERM, which is good.
            if err.errno not in (errno.ENOENT, errno.ESRCH):
                raise
        else:
            rpar = data.rfind(b')')
            dset = data[rpar + 2:].split()
            ppid = int(dset[1])
            ret[pid] = ppid
    return ret 
Example #14
Source File: _pslinux.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def wrap_exceptions(fun):
    """Decorator which translates bare OSError and IOError exceptions
    into NoSuchProcess and AccessDenied.
    """
    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except EnvironmentError as err:
            if err.errno in (errno.EPERM, errno.EACCES):
                raise AccessDenied(self.pid, self._name)
            # ESRCH (no such process) can be raised on read() if
            # process is gone in the meantime.
            if err.errno == errno.ESRCH:
                raise NoSuchProcess(self.pid, self._name)
            # ENOENT (no such file or directory) can be raised on open().
            if err.errno == errno.ENOENT and not os.path.exists("%s/%s" % (
                    self._procfs_path, self.pid)):
                raise NoSuchProcess(self.pid, self._name)
            # Note: zombies will keep existing under /proc until they're
            # gone so there's no way to distinguish them in here.
            raise
    return wrapper 
Example #15
Source File: _pslinux.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def exe(self):
        try:
            return readlink("%s/%s/exe" % (self._procfs_path, self.pid))
        except OSError as err:
            if err.errno in (errno.ENOENT, errno.ESRCH):
                # no such file error; might be raised also if the
                # path actually exists for system processes with
                # low pids (about 0-20)
                if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)):
                    return ""
                else:
                    if not pid_exists(self.pid):
                        raise NoSuchProcess(self.pid, self._name)
                    else:
                        raise ZombieProcess(self.pid, self._name, self._ppid)
            if err.errno in (errno.EPERM, errno.EACCES):
                raise AccessDenied(self.pid, self._name)
            raise 
Example #16
Source File: __init__.py    From teleport with Apache License 2.0 6 votes vote down vote up
def _send_signal(self, sig):
            assert not self.pid < 0, self.pid
            if self.pid == 0:
                # see "man 2 kill"
                raise ValueError(
                    "preventing sending signal to process with PID 0 as it "
                    "would affect every process in the process group of the "
                    "calling process (os.getpid()) instead of PID 0")
            try:
                os.kill(self.pid, sig)
            except OSError as err:
                if err.errno == errno.ESRCH:
                    if OPENBSD and pid_exists(self.pid):
                        # We do this because os.kill() lies in case of
                        # zombie processes.
                        raise ZombieProcess(self.pid, self._name, self._ppid)
                    else:
                        self._gone = True
                        raise NoSuchProcess(self.pid, self._name)
                if err.errno in (errno.EPERM, errno.EACCES):
                    raise AccessDenied(self.pid, self._name)
                raise 
Example #17
Source File: _psaix.py    From teleport with Apache License 2.0 6 votes vote down vote up
def wrap_exceptions(fun):
    """Call callable into a try/except clause and translate ENOENT,
    EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
    """
    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except EnvironmentError as err:
            # support for private module import
            if (NoSuchProcess is None or AccessDenied is None or
                    ZombieProcess is None):
                raise
            # ENOENT (no such file or directory) gets raised on open().
            # ESRCH (no such process) can get raised on read() if
            # process is gone in meantime.
            if err.errno in (errno.ENOENT, errno.ESRCH):
                if not pid_exists(self.pid):
                    raise NoSuchProcess(self.pid, self._name)
                else:
                    raise ZombieProcess(self.pid, self._name, self._ppid)
            if err.errno in (errno.EPERM, errno.EACCES):
                raise AccessDenied(self.pid, self._name)
            raise
    return wrapper 
Example #18
Source File: test_windows.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def wrap_exceptions(fun):
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except OSError as err:
            from psutil._pswindows import ACCESS_DENIED_SET
            if err.errno in ACCESS_DENIED_SET:
                raise psutil.AccessDenied(None, None)
            if err.errno == errno.ESRCH:
                raise psutil.NoSuchProcess(None, None)
            raise
    return wrapper


# ===================================================================
# System APIs
# =================================================================== 
Example #19
Source File: _psosx.py    From vnpy_crypto with MIT License 6 votes vote down vote up
def catch_zombie(proc):
    """There are some poor C APIs which incorrectly raise ESRCH when
    the process is still alive or it's a zombie, or even RuntimeError
    (those who don't set errno). This is here in order to solve:
    https://github.com/giampaolo/psutil/issues/1044
    """
    try:
        yield
    except (OSError, RuntimeError) as err:
        if isinstance(err, RuntimeError) or err.errno == errno.ESRCH:
            try:
                # status() is not supposed to lie and correctly detect
                # zombies so if it raises ESRCH it's true.
                status = proc.status()
            except NoSuchProcess:
                raise err
            else:
                if status == _common.STATUS_ZOMBIE:
                    raise ZombieProcess(proc.pid, proc._name, proc._ppid)
                else:
                    raise AccessDenied(proc.pid, proc._name)
        else:
            raise 
Example #20
Source File: test_lockfile.py    From Safejumper-for-Desktop with GNU General Public License v2.0 6 votes vote down vote up
def test_killError(self):
        """
        If L{kill} raises an exception other than L{OSError} with errno set to
        C{ESRCH}, the exception is passed up to the caller of
        L{FilesystemLock.lock}.
        """
        def fakeKill(pid, signal):
            raise OSError(errno.EPERM, None)
        self.patch(lockfile, 'kill', fakeKill)

        lockf = self.mktemp()

        # Make it appear locked so it has to use readlink
        lockfile.symlink(str(43125), lockf)

        lock = lockfile.FilesystemLock(lockf)
        exc = self.assertRaises(OSError, lock.lock)
        self.assertEqual(exc.errno, errno.EPERM)
        self.assertFalse(lock.locked) 
Example #21
Source File: test_lockfile.py    From Safejumper-for-Desktop with GNU General Public License v2.0 6 votes vote down vote up
def test_rmlinkError(self):
        """
        An exception raised by L{rmlink} other than C{ENOENT} is passed up
        to the caller of L{FilesystemLock.lock}.
        """
        def fakeRmlink(name):
            raise OSError(errno.ENOSYS, None)
        self.patch(lockfile, 'rmlink', fakeRmlink)

        def fakeKill(pid, signal):
            if signal != 0:
                raise OSError(errno.EPERM, None)
            if pid == 43125:
                raise OSError(errno.ESRCH, None)
        self.patch(lockfile, 'kill', fakeKill)

        lockf = self.mktemp()

        # Make it appear locked so it has to use readlink
        lockfile.symlink(str(43125), lockf)

        lock = lockfile.FilesystemLock(lockf)
        exc = self.assertRaises(OSError, lock.lock)
        self.assertEqual(exc.errno, errno.ENOSYS)
        self.assertFalse(lock.locked) 
Example #22
Source File: _psosx.py    From psutil with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def catch_zombie(proc):
    """There are some poor C APIs which incorrectly raise ESRCH when
    the process is still alive or it's a zombie, or even RuntimeError
    (those who don't set errno). This is here in order to solve:
    https://github.com/giampaolo/psutil/issues/1044
    """
    try:
        yield
    except (OSError, RuntimeError) as err:
        if isinstance(err, RuntimeError) or err.errno == errno.ESRCH:
            try:
                # status() is not supposed to lie and correctly detect
                # zombies so if it raises ESRCH it's true.
                status = proc.status()
            except NoSuchProcess:
                raise err
            else:
                if status == _common.STATUS_ZOMBIE:
                    raise ZombieProcess(proc.pid, proc._name, proc._ppid)
                else:
                    raise AccessDenied(proc.pid, proc._name)
        else:
            raise 
Example #23
Source File: test_lockfile.py    From Safejumper-for-Desktop with GNU General Public License v2.0 6 votes vote down vote up
def test_uncleanlyAcquire(self):
        """
        If a lock was held by a process which no longer exists, it can be
        acquired, the C{clean} attribute is set to C{False}, and the
        C{locked} attribute is set to C{True}.
        """
        owner = 12345

        def fakeKill(pid, signal):
            if signal != 0:
                raise OSError(errno.EPERM, None)
            if pid == owner:
                raise OSError(errno.ESRCH, None)

        lockf = self.mktemp()
        self.patch(lockfile, 'kill', fakeKill)
        lockfile.symlink(str(owner), lockf)

        lock = lockfile.FilesystemLock(lockf)
        self.assertTrue(lock.lock())
        self.assertFalse(lock.clean)
        self.assertTrue(lock.locked)

        self.assertEqual(lockfile.readlink(lockf), str(os.getpid())) 
Example #24
Source File: cross_platform_process.py    From sublime-gulp with MIT License 6 votes vote down vote up
def _pid_exists(self):
        if not self.pid:
            return False

        if sublime.platform() == "windows":
            taskkill = subprocess.Popen(['C:\\Windows\\system32\\tasklist.exe', '/FI', 'PID eq %s' % self.pid, '/FO', 'CSV'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
            (stdout, stderr) = taskkill.communicate()

            failed = taskkill.returncode == 127 or stderr
            found = str(self.pid) in CrossPlatformCodecs.force_decode(stdout)

            return found or failed
        else:
            try:
                os.kill(self.pid, 0)
            except OSError as err:
                if err.errno == errno.ESRCH:
                    return False
                elif err.errno == errno.EPERM:
                    return True
                else:
                    raise
            else:
                return True 
Example #25
Source File: servers.py    From oss-ftp with MIT License 6 votes vote down vote up
def close_all(self):
        tasks = self._active_tasks[:]
        # this must be set after getting active tasks as it causes
        # thread objects to get out of the list too soon
        self._exit.set()
        if tasks and hasattr(tasks[0], 'terminate'):
            # we're dealing with subprocesses
            for t in tasks:
                try:
                    if not _BSD:
                        t.terminate()
                    else:
                        # XXX - On FreeBSD using SIGTERM doesn't work
                        # as the process hangs on kqueue.control() or
                        # select.select(). Use SIGKILL instead.
                        os.kill(t.pid, signal.SIGKILL)
                except OSError as err:
                    if err.errno != errno.ESRCH:
                        raise

        self._wait_for_tasks(tasks)
        del self._active_tasks[:]
        FTPServer.close_all(self) 
Example #26
Source File: servers.py    From oss-ftp with MIT License 6 votes vote down vote up
def _wait_for_tasks(self, tasks):
        """Wait for threads or subprocesses to terminate."""
        warn = logger.warning
        for t in tasks:
            t.join(self.join_timeout)
            if t.is_alive():
                # Thread or process is still alive. If it's a process
                # attempt to send SIGKILL as last resort.
                # Set timeout to None so that we will exit immediately
                # in case also other threads/processes are hanging.
                self.join_timeout = None
                if hasattr(t, 'terminate'):
                    msg = "could not terminate process %r" % t
                    if not _BSD:
                        warn(msg + "; sending SIGKILL as last resort")
                        try:
                            os.kill(t.pid, signal.SIGKILL)
                        except OSError as err:
                            if err.errno != errno.ESRCH:
                                raise
                    else:
                        warn(msg)
                else:
                    warn("thread %r didn't terminate; ignoring it", t) 
Example #27
Source File: servers.py    From oss-ftp with MIT License 6 votes vote down vote up
def close_all(self):
        tasks = self._active_tasks[:]
        # this must be set after getting active tasks as it causes
        # thread objects to get out of the list too soon
        self._exit.set()
        if tasks and hasattr(tasks[0], 'terminate'):
            # we're dealing with subprocesses
            for t in tasks:
                try:
                    if not _BSD:
                        t.terminate()
                    else:
                        # XXX - On FreeBSD using SIGTERM doesn't work
                        # as the process hangs on kqueue.control() or
                        # select.select(). Use SIGKILL instead.
                        os.kill(t.pid, signal.SIGKILL)
                except OSError as err:
                    if err.errno != errno.ESRCH:
                        raise

        self._wait_for_tasks(tasks)
        del self._active_tasks[:]
        FTPServer.close_all(self) 
Example #28
Source File: servers.py    From oss-ftp with MIT License 6 votes vote down vote up
def _wait_for_tasks(self, tasks):
        """Wait for threads or subprocesses to terminate."""
        warn = logger.warning
        for t in tasks:
            t.join(self.join_timeout)
            if t.is_alive():
                # Thread or process is still alive. If it's a process
                # attempt to send SIGKILL as last resort.
                # Set timeout to None so that we will exit immediately
                # in case also other threads/processes are hanging.
                self.join_timeout = None
                if hasattr(t, 'terminate'):
                    msg = "could not terminate process %r" % t
                    if not _BSD:
                        warn(msg + "; sending SIGKILL as last resort")
                        try:
                            os.kill(t.pid, signal.SIGKILL)
                        except OSError as err:
                            if err.errno != errno.ESRCH:
                                raise
                    else:
                        warn(msg)
                else:
                    warn("thread %r didn't terminate; ignoring it", t) 
Example #29
Source File: test_pidfile.py    From Safejumper-for-Desktop with GNU General Public License v2.0 6 votes vote down vote up
def test_contextManagerDoesntExist(self):
        """
        When used as a context manager, a L{PIDFile} will replace the
        underlying PIDFile rather than raising L{AlreadyRunningError} if the
        contained PID file exists but refers to a non-running PID.
        """
        pidFile = PIDFile(DummyFilePath())
        pidFile._write(1337)

        def kill(pid, signal):
            raise OSError(errno.ESRCH, "No such process")

        self.patch(_pidfile, "kill", kill)

        e = self.assertRaises(StalePIDFileError, pidFile.isRunning)
        self.assertEqual(str(e), "PID file refers to non-existing process")

        with pidFile:
            self.assertEqual(pidFile.read(), getpid()) 
Example #30
Source File: process.py    From Safejumper-for-Desktop with GNU General Public License v2.0 6 votes vote down vote up
def signalProcess(self, signalID):
        """
        Send the given signal C{signalID} to the process. It'll translate a
        few signals ('HUP', 'STOP', 'INT', 'KILL', 'TERM') from a string
        representation to its int value, otherwise it'll pass directly the
        value provided

        @type signalID: C{str} or C{int}
        """
        if signalID in ('HUP', 'STOP', 'INT', 'KILL', 'TERM'):
            signalID = getattr(signal, 'SIG%s' % (signalID,))
        if self.pid is None:
            raise ProcessExitedAlready()
        try:
            os.kill(self.pid, signalID)
        except OSError as e:
            if e.errno == errno.ESRCH:
                raise ProcessExitedAlready()
            else:
                raise