Exemplo n.º 1
0
def is_running(pid):
    """Check whether a process with the given pid is running.

    :param pid: an integer (e.g the value of Run().pid)
    :type pid: int

    :rtype: bool
    """
    if sys.platform == 'win32':  # unix: no cover
        from e3.os.windows.native_api import Access, NT
        from e3.os.windows.process import process_exit_code
        handle = NT.OpenProcess(Access.PROCESS_QUERY_INFORMATION, False, pid)

        try:
            if not handle:
                return False
            return process_exit_code(handle) is None

        finally:
            NT.Close(handle)

    else:  # windows: no cover
        try:
            # We send a null signal to check the validity of pid
            os.kill(pid, 0)
        except OSError as e:
            # If the process is not found, errno will be set to ESRCH
            return e.errno != errno.ESRCH
        return True
Exemplo n.º 2
0
def is_running(pid):
    """Check whether a process with the given pid is running.

    :param pid: an integer (e.g the value of Run().pid)
    :type pid: int

    :rtype: bool
    """
    if sys.platform == 'win32':  # unix: no cover
        from e3.os.windows.native_api import Access, NT
        from e3.os.windows.process import process_exit_code
        handle = NT.OpenProcess(Access.PROCESS_QUERY_INFORMATION, False, pid)

        try:
            if handle == 0:
                return False

            return process_exit_code(handle) is None

        finally:
            NT.Close(handle)

    else:
        try:
            # We send a null signal to check the validity of pid
            os.kill(pid, 0)
        except OSError as e:
            # If the process is not found, errno will be set to ESRCH
            return e.errno != errno.ESRCH
        return True
Exemplo n.º 3
0
def wait_for_processes(process_list, timeout):
    """Wait for several processes spawned with Run.

    :param process_list: a list of Run objects
    :type process_list: list[Run]
    :param timeout: a timeout in seconds. If 0 block until a process ends.
    :type timeout: int

    :return: None in case of timeout or the index in process Run corresponding
        to the first process that end
    :rtype: None | int
    """
    if len(process_list) == 0:
        return None

    start = time.time()
    remain = timeout

    if sys.platform == 'win32':  # unix: no cover
        from e3.os.windows.process import process_exit_code, wait_for_objects

        handles = [int(p.internal._handle) for p in process_list]

        while True:
            try:
                idx = wait_for_objects(handles, remain, False)
                if idx is None:
                    return

                if process_exit_code(handles[idx]) is None:
                    # Process is still active so wait after updating timeout
                    remain = timeout - time.time() + start

                    if remain <= 0:
                        # No remaining time
                        return None
                else:
                    # Process is exiting so finalize it by calling wait
                    process_list[idx].wait()
                    return idx
            except OSError:
                raise WaitError

    else:  # windows: no cover
        import select

        # Each time a SIGCHLD signal is received write into pipe. Use
        # then select which support timeout arguments to wait.
        fd_r, fd_w = os.pipe()

        def handler(signum, frame):
            del signum, frame
            os.write(fd_w, b'a')

        signal.signal(signal.SIGCHLD, handler)

        try:
            while remain >= 0.0 or timeout == 0:
                # Do a first check in case a SIGCHLD was emited before the
                # initialisation of the handler.
                for index, p in enumerate(process_list):
                    if p.poll() is not None:
                        return index

                # Wait for a sigchld signal. Note that select might
                # be interrupted by signals thus the loop
                select_args = [[fd_r], [], []]
                if timeout != 0:
                    select_args.append(remain)

                while True:
                    try:
                        l_r, _, _ = select.select(*select_args)
                        if l_r:
                            os.read(fd_r, 1)
                        break
                    except select.error:
                        pass

                remain = timeout - time.time() + start

            logger.warning('no process ended after %f seconds',
                           time.time() - start)  # defensive code

        finally:
            # Be sure to remove signal handler and close pipe
            signal.signal(signal.SIGCHLD, 0)
            os.close(fd_r)
            os.close(fd_w)
Exemplo n.º 4
0
def test_invalid_handle():
    with pytest.raises(WindowsError):
        process_exit_code(42)
Exemplo n.º 5
0
def wait_for_processes(process_list, timeout):
    """Wait for several processes spawned with Run.

    :param process_list: a list of Run objects
    :type process_list: list[Run]
    :param timeout: a timeout in seconds. If 0 block until a process ends.
    :type timeout: int

    :return: None in case of timeout or the index in process Run corresponding
        to the first process that end
    :rtype: None | int
    """
    if len(process_list) == 0:
        return None

    start = time.time()
    remain = timeout

    if sys.platform == 'win32':  # unix: no cover
        from e3.os.windows.process import process_exit_code, wait_for_objects

        handles = [int(p.internal._handle) for p in process_list]

        while True:
            try:
                idx = wait_for_objects(handles, remain, False)
                if idx is None:
                    return

                if process_exit_code(handles[idx]) is None:
                    # Process is still active so wait after updating timeout
                    remain = timeout - time.time() + start

                    if remain <= 0:
                        # No remaining time
                        return None
                else:
                    # Process is exiting so finalize it by calling wait
                    process_list[idx].wait()
                    return idx
            except OSError:
                raise WaitError

    else:
        import e3.os.unix.process
        # Choose between blocking or non-blocking call to wait
        blocking = True
        if timeout != 0:
            blocking = False

        while remain >= 0.0 or timeout == 0:
            # Retrieve first child process that ends. Note that that child
            # process might not be in our watch list
            pid = e3.os.unix.process.wait(blocking)

            if pid != 0:
                # We have a result
                result = next((index for index, p in
                               enumerate(process_list) if p.pid == pid), None)
                if result is not None:
                    # At the stage we need to set the process status and close
                    # related handles. Indeed we will not be able to use the
                    # wait method afterwards and retrieve it.
                    process_list[result].wait()
                    return result
            time.sleep(1.0)
            remain = timeout - time.time() + start
        return None