class Main: @staticmethod def send_data(sock: SCTSock, code: ErrorCodes, data=None): sock.send_data({"res": code, "data": data}) sock.close() def __init__(self, threads:int=20, listener_timeout:int=600, request_timeout:int=50): self._request_timout = request_timeout signal.signal(signal.SIGTERM, self.stop) self._pool = multiprocessing.pool.ThreadPool(threads + 1) self._lock = multiprocessing.Lock() self._plugin = Plugin() self._timeout = Timeout(self.stop, listener_timeout) self._connections = Connections(threads) self._listener = Listener(self.handle_connection) self._listener.run() def stop(self, signum:int=0, frame=None): self._timeout.stop() self._listener.close() self._connections.apply(lambda con: self.send_data(con, ErrorCodes.listener_timeout)) self._pool.close() def handle_connection(self, sock: SCTSock): self._pool.apply_async(self._handle_connection_thread, [sock]) def _handle_connection_thread(self, sock: SCTSock): try: with ConnectionsWrapper(sock, self._connections): self._timeout.reset() with self._lock: version = sock.recv().payload if not self._plugin.checkVersion(version): sock.send_init("init") data = sock.recv().payload self._plugin.setSettings(version, data) sock.send_init("data") con_pool = multiprocessing.pool.ThreadPool(1) data = sock.recv().payload result = con_pool.apply_async(self._plugin.exec, [data]).get( self._request_timout ) con_pool.close() self.send_data(sock, ErrorCodes.none, result) except multiprocessing.TimeoutError: self.send_data(sock, ErrorCodes.execution_timeout) except TooManyConnectionsError: self.send_data(sock, ErrorCodes.too_many_connections) except Exception as e: traceback = get_traceback(e) self.send_data(sock, ErrorCodes.exception, traceback) print(traceback) finally: sock.close()