def __enter__(self) -> 'IPCServer': if sys.platform == 'win32': # NOTE: It is theoretically possible that this will hang forever if the # client never connects, though this can be "solved" by killing the server try: ov = _winapi.ConnectNamedPipe(self.connection, overlapped=True) # TODO: remove once typeshed supports Literal types assert isinstance(ov, _winapi.Overlapped) except OSError as e: # Don't raise if the client already exists, or the client already connected if e.winerror not in (_winapi.ERROR_PIPE_CONNECTED, _winapi.ERROR_NO_DATA): raise else: try: timeout = int(self.timeout * 1000) if self.timeout else _winapi.INFINITE res = _winapi.WaitForSingleObject(ov.event, timeout) assert res == _winapi.WAIT_OBJECT_0 except BaseException: ov.cancel() _winapi.CloseHandle(self.connection) raise _, err = ov.GetOverlappedResult(True) assert err == 0 else: try: self.connection, _ = self.sock.accept() except socket.timeout as e: raise IPCException('The socket timed out') from e return self
def _pid_alive(pid): """Check if the process with this PID is alive or not. Args: pid: The pid to check. Returns: This returns false if the process is dead. Otherwise, it returns true. """ no_such_process = errno.EINVAL if sys.platform == "win32" else errno.ESRCH alive = True try: if sys.platform == "win32": SYNCHRONIZE = 0x00100000 # access mask defined in <winnt.h> handle = _winapi.OpenProcess(SYNCHRONIZE, False, pid) try: alive = (_winapi.WaitForSingleObject(handle, 0) != _winapi.WAIT_OBJECT_0) finally: _winapi.CloseHandle(handle) else: os.kill(pid, 0) except OSError as ex: if ex.errno != no_such_process: raise alive = False return alive
def write(self, data: bytes) -> None: """Write bytes to an IPC connection.""" if sys.platform == 'win32': try: ov, err = _winapi.WriteFile(self.connection, data, overlapped=True) # TODO: remove once typeshed supports Literal types assert isinstance(ov, _winapi.Overlapped) assert isinstance(err, int) try: if err == _winapi.ERROR_IO_PENDING: timeout = int( self.timeout * 1000) if self.timeout else _winapi.INFINITE res = _winapi.WaitForSingleObject(ov.event, timeout) if res != _winapi.WAIT_OBJECT_0: raise IPCException( f"Bad result from I/O wait: {res}") elif err != 0: raise IPCException( f"Failed writing to pipe with error: {err}") except BaseException: ov.cancel() raise bytes_written, err = ov.GetOverlappedResult(True) assert err == 0, err assert bytes_written == len(data) except OSError as e: raise IPCException( f"Failed to write with error: {e.winerror}") from e else: self.connection.sendall(data) self.connection.shutdown(socket.SHUT_WR)
def _wait_pid(self, blocking): assert self.__handle is not None if blocking: timeout = _winapi.INFINITE else: timeout = 0 result = _winapi.WaitForSingleObject(self.__handle, timeout) if result != _winapi.WAIT_TIMEOUT: self.__result = _winapi.GetExitCodeProcess(self._handle)
def wait(self, timeout=None): if self.returncode is None: if timeout is None: msecs = _winapi.INFINITE else: msecs = max(0, int(timeout * 1000 + 0.5)) res = _winapi.WaitForSingleObject(int(self._handle), msecs) if res == _winapi.WAIT_OBJECT_0: code = _winapi.GetExitCodeProcess(self._handle) if code == TERMINATE: code = -signal.SIGTERM self.returncode = code return self.returncode
def wait(self, timeout=None, endtime=None): if endtime is not None: timeout = self._remaining_time(endtime) if timeout is None: timeout_millis = _winapi.INFINITE else: timeout_millis = int(timeout*1000) if self.returncode is None: result = _winapi.WaitForSingleObject(self._handle, timeout_millis) if result == _winapi.WAIT_TIMEOUT: raise TimeoutExpired(self.args, timeout) self.returncode = _winapi.GetExitCodeProcess(self._handle) return self.returncode
def finish(trans, key, ov): if not f.cancelled(): try: _overlapped.UnregisterWait(wh) except OSError as e: if e.winerror != _overlapped.ERROR_IO_PENDING: raise # Note that this second wait means that we should only use # this with handles types where a successful wait has no # effect. So events or processes are all right, but locks # or semaphores are not. Also note if the handle is # signalled and then quickly reset, then we may return # False even though we have not timed out. return (_winapi.WaitForSingleObject(handle, 0) == _winapi.WAIT_OBJECT_0)
def read(self, size: int = 100000) -> bytes: """Read bytes from an IPC connection until its empty.""" bdata = bytearray() if sys.platform == 'win32': while True: ov, err = _winapi.ReadFile(self.connection, size, overlapped=True) # TODO: remove once typeshed supports Literal types assert isinstance(ov, _winapi.Overlapped) assert isinstance(err, int) try: if err == _winapi.ERROR_IO_PENDING: timeout = int( self.timeout * 1000) if self.timeout else _winapi.INFINITE res = _winapi.WaitForSingleObject(ov.event, timeout) if res != _winapi.WAIT_OBJECT_0: raise IPCException( "Bad result from I/O wait: {}".format(res)) except BaseException: ov.cancel() raise _, err = ov.GetOverlappedResult(True) more = ov.getbuffer() if more: bdata.extend(more) if err == 0: # we are done! break elif err == _winapi.ERROR_MORE_DATA: # read again continue elif err == _winapi.ERROR_OPERATION_ABORTED: raise IPCException("ReadFile operation aborted.") else: while True: more = self.connection.recv(size) if not more: break bdata.extend(more) return bytes(bdata)
def _poll(self): # non-blocking wait: use a timeout of 0 millisecond return (_winapi.WaitForSingleObject(self._handle, 0) == _winapi.WAIT_OBJECT_0)
def _poll(self): return _winapi.WaitForSingleObject(self._handle, 0 ) == _winapi.WAIT_OBJECT_0