def __init__(self, uid, gid, env_options, session_options, socket_dir, video_encoder_modules, pings, client_conn, disp_desc, client_state, cipher, encryption_key, server_conn, caps, message_queue): ProxyInstance.__init__(self, session_options, video_encoder_modules, pings, disp_desc, cipher, encryption_key, caps) QueueScheduler.__init__(self) Process.__init__(self, name=str(client_conn), daemon=False) self.client_conn = client_conn self.server_conn = server_conn self.uid = uid self.gid = gid self.env_options = env_options self.socket_dir = socket_dir self.client_state = client_state log("ProxyProcess%s", (uid, gid, env_options, session_options, socket_dir, video_encoder_modules, client_conn, disp_desc, ellipsizer(client_state), cipher, encryption_key, server_conn, "%s: %s.." % (type(caps), ellipsizer(caps)), message_queue)) self.message_queue = message_queue #for handling the local unix domain socket: self.control_socket_cleanup = None self.control_socket = None self.control_socket_thread = None self.control_socket_path = None self.potential_protocols = [] self.max_connections = MAX_CONCURRENT_CONNECTIONS
def signal_quit(self, signum, _frame=None): log.info("") log.info("proxy process pid %s got signal %s, exiting", os.getpid(), SIGNAMES.get(signum, signum)) QueueScheduler.stop(self) self.message_queue.put(None, False) signal.signal(signal.SIGINT, deadly_signal) signal.signal(signal.SIGTERM, deadly_signal) self.stop(None, SIGNAMES.get(signum, signum))
def test_idle_timeout(self): qs = QueueScheduler() calls = [] def idle_add(arg): calls.append(arg) qs.idle_add(idle_add, True) def timeout_add(arg): calls.append(arg) qs.timeout_add(100, timeout_add, True) qs.timeout_add(500, qs.stop) qs.run() assert len(calls)==2
def run(self): register_SIGUSR_signals(self.idle_add) client_protocol_class = get_client_protocol_class(self.client_conn.socktype) server_protocol_class = get_server_protocol_class(self.server_conn.socktype) self.client_protocol = client_protocol_class(self, self.client_conn, self.process_client_packet, self.get_client_packet) self.client_protocol.restore_state(self.client_state) self.server_protocol = server_protocol_class(self, self.server_conn, self.process_server_packet, self.get_server_packet) self.log_start() log("ProxyProcessProcess.run() pid=%s, uid=%s, gid=%s", os.getpid(), getuid(), getgid()) set_proc_title("Xpra Proxy Instance for %s" % self.server_conn) if POSIX and (getuid()!=self.uid or getgid()!=self.gid): #do we need a valid XDG_RUNTIME_DIR for the socket-dir? username = get_username_for_uid(self.uid) socket_dir = osexpand(self.socket_dir, username, self.uid, self.gid) if not os.path.exists(socket_dir): log("the socket directory '%s' does not exist, checking for $XDG_RUNTIME_DIR path", socket_dir) for prefix in ("/run/user/", "/var/run/user/"): if socket_dir.startswith(prefix): from xpra.scripts.server import create_runtime_dir xrd = os.path.join(prefix, str(self.uid)) #ie: /run/user/99 log("creating XDG_RUNTIME_DIR=%s for uid=%i, gid=%i", xrd, self.uid, self.gid) create_runtime_dir(xrd, self.uid, self.gid) break #change uid or gid: setuidgid(self.uid, self.gid) if self.env_options: #TODO: whitelist env update? os.environ.update(self.env_options) signal.signal(signal.SIGTERM, self.signal_quit) signal.signal(signal.SIGINT, self.signal_quit) log("registered signal handler %s", self.signal_quit) start_thread(self.server_message_queue, "server message queue") if not self.create_control_socket(): return self.control_socket_thread = start_thread(self.control_socket_loop, "control", daemon=True) self.main_queue = Queue() ProxyInstance.run(self) try: QueueScheduler.run(self) except KeyboardInterrupt as e: self.stop(None, str(e)) finally: log("ProxyProcess.run() ending %s", os.getpid())
def test_source_remove(self): qs = QueueScheduler() calls = [] def timeout_add(arg): calls.append(arg) t = qs.timeout_add(100, timeout_add, True) qs.source_remove(t) qs.timeout_add(500, qs.stop) qs.run() assert not calls
def test_idle_raises_exception(self): qs = QueueScheduler() def raise_exception(): raise Exception("test scheduler error handling") with silence_error(log): qs.idle_add(raise_exception) qs.timeout_add(500, qs.stop) qs.run()
def test_idle_repeat(self): qs = QueueScheduler() calls = [] def idle_add(arg): calls.append(arg) return len(calls)<10 qs.idle_add(idle_add, True) qs.timeout_add(500, qs.stop) qs.run() assert len(calls)==10
def test_timer_repeat(self): times = list(range(10)) def timer_fn(): times.pop() return len(times) > 0 qs = QueueScheduler() qs.timeout_add(1, timer_fn) qs.timeout_add(500, qs.stop) qs.run() assert not times
def test_timer_repeat(self): times = list(range(10)) qs = QueueScheduler() def timer_fn(): times.pop() if not times: qs.stop() return False return True qs.timeout_add(1, timer_fn) qs.timeout_add(2000, qs.stop) qs.run() assert not times, "items remain in list: %s" % (times, )
def test_timeout_cancel(self): qs = QueueScheduler() calls = [] def timeout_add(): calls.append(True) return True tid = qs.timeout_add(10, timeout_add) copy = [] def cancel(): qs.source_remove(tid) copy[:] = list(calls) return False qs.timeout_add(500, cancel) qs.timeout_add(1000, qs.stop) qs.run() assert len(calls) == len(copy), "idle_add continued to run!"
def stop(self, skip_proto, *reasons): QueueScheduler.stop(self) self.message_queue.put_nowait(None) super().stop(skip_proto, *reasons) self.stop_control_socket()
def test_invalid_remove(self): qs = QueueScheduler() qs.source_remove(-1)
def test_stop_queue(self): qs = QueueScheduler() qs.idle_add(qs.stop_main_queue) qs.run()
def stop(self, skip_proto, *reasons): ProxyInstance.stop(self, skip_proto, *reasons) self.stop_control_socket() QueueScheduler.stop(self)