def request(status_file: str, command: str, *, timeout: Optional[int] = None, **kwds: object) -> Dict[str, Any]: """Send a request to the daemon. Return the JSON dict with the response. Raise BadStatus if there is something wrong with the status file or if the process whose pid is in the status file has died. Return {'error': <message>} if an IPC operation or receive() raised OSError. This covers cases such as connection refused or closed prematurely as well as invalid JSON received. """ response = {} # type: Dict[str, str] args = dict(kwds) args['command'] = command # Tell the server whether this request was initiated from a human-facing terminal, # so that it can format the type checking output accordingly. args['is_tty'] = sys.stdout.isatty() args['terminal_width'] = get_terminal_width() bdata = json.dumps(args).encode('utf8') _, name = get_status(status_file) try: with IPCClient(name, timeout) as client: client.write(bdata) response = receive(client) except (OSError, IPCException) as err: return {'error': str(err)} # TODO: Other errors, e.g. ValueError, UnicodeError else: return response
def request(command: str, *, timeout: Optional[float] = None, **kwds: object) -> Dict[str, Any]: """Send a request to the daemon. Return the JSON dict with the response. Raise BadStatus if there is something wrong with the status file or if the process whose pid is in the status file has died. Return {'error': <message>} if a socket operation or receive() raised OSError. This covers cases such as connection refused or closed prematurely as well as invalid JSON received. """ args = dict(kwds) args.update(command=command) bdata = json.dumps(args).encode('utf8') pid, sockname = get_status() sock = socket.socket(socket.AF_UNIX) if timeout is not None: sock.settimeout(timeout) try: sock.connect(sockname) sock.sendall(bdata) sock.shutdown(socket.SHUT_WR) response = receive(sock) except OSError as err: return {'error': str(err)} # TODO: Other errors, e.g. ValueError, UnicodeError else: return response finally: sock.close()
def request(status_file: str, command: str, *, timeout: Optional[int] = None, **kwds: object) -> Dict[str, Any]: """Send a request to the daemon. Return the JSON dict with the response. Raise BadStatus if there is something wrong with the status file or if the process whose pid is in the status file has died. Return {'error': <message>} if an IPC operation or receive() raised OSError. This covers cases such as connection refused or closed prematurely as well as invalid JSON received. """ response = {} # type: Dict[str, str] args = dict(kwds) args.update(command=command) bdata = json.dumps(args).encode('utf8') _, name = get_status(status_file) try: with IPCClient(name, timeout) as client: client.write(bdata) response = receive(client) except (OSError, IPCException) as err: return {'error': str(err)} # TODO: Other errors, e.g. ValueError, UnicodeError else: return response
def serve(self) -> None: """Serve requests, synchronously (no thread or fork).""" try: sock = self.create_listening_socket() if self.timeout is not None: sock.settimeout(self.timeout) try: with open(STATUS_FILE, 'w') as f: json.dump( { 'pid': os.getpid(), 'sockname': sock.getsockname() }, f) f.write('\n') # I like my JSON with trailing newline while True: try: conn, addr = sock.accept() except socket.timeout: print("Exiting due to inactivity.") self.free_global_state() sys.exit(0) try: data = receive(conn) except OSError as err: conn.close() # Maybe the client hung up continue resp = {} # type: Dict[str, Any] if 'command' not in data: resp = {'error': "No command found in request"} else: command = data['command'] if not isinstance(command, str): resp = {'error': "Command is not a string"} else: command = data.pop('command') try: resp = self.run_command(command, data) except Exception: # If we are crashing, report the crash to the client tb = traceback.format_exception( *sys.exc_info()) # type: ignore resp = {'error': "Daemon crashed!\n" + "".join(tb)} conn.sendall(json.dumps(resp).encode('utf8')) raise try: conn.sendall(json.dumps(resp).encode('utf8')) except OSError as err: pass # Maybe the client hung up conn.close() if command == 'stop': sock.close() self.free_global_state() sys.exit(0) finally: os.unlink(STATUS_FILE) finally: os.unlink(self.sockname) exc_info = sys.exc_info() if exc_info[0] and exc_info[0] is not SystemExit: traceback.print_exception(*exc_info) # type: ignore
def serve(self) -> None: """Serve requests, synchronously (no thread or fork).""" try: sock = self.create_listening_socket() try: with open(STATUS_FILE, 'w') as f: json.dump({'pid': os.getpid(), 'sockname': sock.getsockname()}, f) f.write('\n') # I like my JSON with trailing newline while True: conn, addr = sock.accept() data = receive(conn) resp = {} # type: Dict[str, Any] if 'command' not in data: resp = {'error': "No command found in request"} else: command = data['command'] if not isinstance(command, str): resp = {'error': "Command is not a string"} else: command = data.pop('command') resp = self.run_command(command, data) try: conn.sendall(json.dumps(resp).encode('utf8')) except OSError as err: pass # Maybe the client hung up conn.close() if command == 'stop': sock.close() sys.exit(0) finally: os.unlink(STATUS_FILE) finally: os.unlink(self.sockname)
def serve(self) -> None: """Serve requests, synchronously (no thread or fork).""" command = None try: server = IPCServer(CONNECTION_NAME, self.timeout) with open(self.status_file, 'w') as f: json.dump( { 'pid': os.getpid(), 'connection_name': server.connection_name }, f) f.write('\n') # I like my JSON with a trailing newline while True: with server: data = receive(server) resp = {} # type: Dict[str, Any] if 'command' not in data: resp = {'error': "No command found in request"} else: command = data['command'] if not isinstance(command, str): resp = {'error': "Command is not a string"} else: command = data.pop('command') try: resp = self.run_command(command, data) except Exception: # If we are crashing, report the crash to the client tb = traceback.format_exception( *sys.exc_info()) resp = { 'error': "Daemon crashed!\n" + "".join(tb) } resp.update(self._response_metadata()) server.write(json.dumps(resp).encode('utf8')) raise try: resp.update(self._response_metadata()) server.write(json.dumps(resp).encode('utf8')) except OSError: pass # Maybe the client hung up if command == 'stop': reset_global_state() sys.exit(0) finally: # If the final command is something other than a clean # stop, remove the status file. (We can't just # simplify the logic and always remove the file, since # that could cause us to remove a future server's # status file.) if command != 'stop': os.unlink(self.status_file) try: server.cleanup() # try to remove the socket dir on Linux except OSError: pass exc_info = sys.exc_info() if exc_info[0] and exc_info[0] is not SystemExit: traceback.print_exception(*exc_info)
def serve(self) -> None: """Serve requests, synchronously (no thread or fork).""" try: sock = self.create_listening_socket() if self.timeout is not None: sock.settimeout(self.timeout) try: with open(STATUS_FILE, 'w') as f: json.dump({'pid': os.getpid(), 'sockname': sock.getsockname()}, f) f.write('\n') # I like my JSON with trailing newline while True: try: conn, addr = sock.accept() except socket.timeout: print("Exiting due to inactivity.") sys.exit(0) try: data = receive(conn) except OSError as err: conn.close() # Maybe the client hung up continue resp = {} # type: Dict[str, Any] if 'command' not in data: resp = {'error': "No command found in request"} else: command = data['command'] if not isinstance(command, str): resp = {'error': "Command is not a string"} else: command = data.pop('command') try: resp = self.run_command(command, data) except Exception: # If we are crashing, report the crash to the client tb = traceback.format_exception(*sys.exc_info()) # type: ignore resp = {'error': "Daemon crashed!\n" + "".join(tb)} conn.sendall(json.dumps(resp).encode('utf8')) raise try: conn.sendall(json.dumps(resp).encode('utf8')) except OSError as err: pass # Maybe the client hung up conn.close() if command == 'stop': sock.close() sys.exit(0) finally: os.unlink(STATUS_FILE) finally: os.unlink(self.sockname) exc_info = sys.exc_info() if exc_info[0] and exc_info[0] is not SystemExit: traceback.print_exception(*exc_info) # type: ignore
def serve(self) -> None: """Serve requests, synchronously (no thread or fork).""" command = None try: server = IPCServer(CONNECTION_NAME, self.timeout) with open(self.status_file, 'w') as f: json.dump({'pid': os.getpid(), 'connection_name': server.connection_name}, f) f.write('\n') # I like my JSON with a trailing newline while True: with server: data = receive(server) resp = {} # type: Dict[str, Any] if 'command' not in data: resp = {'error': "No command found in request"} else: command = data['command'] if not isinstance(command, str): resp = {'error': "Command is not a string"} else: command = data.pop('command') try: resp = self.run_command(command, data) except Exception: # If we are crashing, report the crash to the client tb = traceback.format_exception(*sys.exc_info()) resp = {'error': "Daemon crashed!\n" + "".join(tb)} resp.update(self._response_metadata()) server.write(json.dumps(resp).encode('utf8')) raise try: resp.update(self._response_metadata()) server.write(json.dumps(resp).encode('utf8')) except OSError: pass # Maybe the client hung up if command == 'stop': reset_global_state() sys.exit(0) finally: # If the final command is something other than a clean # stop, remove the status file. (We can't just # simplify the logic and always remove the file, since # that could cause us to remove a future server's # status file.) if command != 'stop': os.unlink(self.status_file) try: server.cleanup() # try to remove the socket dir on Linux except OSError: pass exc_info = sys.exc_info() if exc_info[0] and exc_info[0] is not SystemExit: traceback.print_exception(*exc_info)
def serve(self) -> None: """Serve requests, synchronously (no thread or fork).""" try: sock = self.create_listening_socket() try: with open(STATUS_FILE, 'w') as f: json.dump( { 'pid': os.getpid(), 'sockname': sock.getsockname() }, f) f.write('\n') # I like my JSON with trailing newline while True: conn, addr = sock.accept() data = receive(conn) resp = {} # type: Dict[str, Any] if 'command' not in data: resp = {'error': "No command found in request"} else: command = data['command'] if not isinstance(command, str): resp = {'error': "Command is not a string"} else: command = data.pop('command') resp = self.run_command(command, data) try: conn.sendall(json.dumps(resp).encode('utf8')) except OSError as err: pass # Maybe the client hung up conn.close() if command == 'stop': sock.close() sys.exit(0) finally: os.unlink(STATUS_FILE) finally: os.unlink(self.sockname) exc_info = sys.exc_info() if exc_info[0]: traceback.print_exception(*exc_info) # type: ignore
def request(command: str, **kwds: object) -> Dict[str, Any]: """Send a request to the daemon. Return the JSON dict with the response. """ args = dict(kwds) if command: args.update(command=command) data = json.dumps(args) pid, sockname = get_status() sock = socket.socket(socket.AF_UNIX) sock.connect(sockname) sock.sendall(data.encode('utf8')) sock.shutdown(socket.SHUT_WR) try: response = receive(sock) except OSError as err: return {'error': str(err)} else: return response finally: sock.close()