def show_selected_session(self): #show this session: try: self.cleanup() env = os.environ.copy() #we only deal with local sessions, should be fast: env["XPRA_CONNECT_TIMEOUT"] = "3" proc = self.do_run_subcommand("top", env=env) if not proc: self.message = monotonic( ), "failed to execute subprocess", curses.color_pair(RED) return exit_code = proc.wait() txt = "top subprocess terminated" attr = 0 if exit_code != 0: attr = curses.color_pair(RED) txt += " with error code %i" % exit_code if exit_code in EXIT_STR: txt += " (%s)" % EXIT_STR.get(exit_code, "").replace( "_", " ") elif (exit_code - 128) in SIGNAMES: #pylint: disable=superfluous-parens txt += " (%s)" % SIGNAMES[exit_code - 128] self.message = monotonic(), txt, attr finally: self.setup()
def reconnect(exit_code): log("reconnect(%s) config reconnect=%s", EXIT_STR.get(exit_code, exit_code), self.config.reconnect) if not self.config.reconnect or exit_code not in RETRY_EXIT_CODES: return False self.clean_client() #give time for the main loop to run once after calling cleanup GLib.timeout_add(100, self.start_client, display_desc) return True
def getoutput(cmd, env=None): try: process = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT, env=env, close_fds=True) except Exception as e: print("error running %s: %s" % (cmd, e)) raise e out, err = process.communicate() code = process.poll() if code!=0: raise Exception("command '%s' returned error code %i: %s, out=%s, err=%s" % (cmd, code, EXIT_STR.get(code), out, err)) return out
def proc_exit(*args): log("proc_exit%s", args) c = proc.poll() if key in self.clients_disconnecting: self.clients_disconnecting.remove(key) elif c not in (0, None): self.warning.set_text(EXIT_STR.get(c, "exit code %s" % c).replace("_", " ")) client_proc = self.clients.pop(key, None) if client_proc: def update(): self.update() self.populate() GLib.idle_add(update)
def do_test_connect(self, disconnect=True, client_args=(), server_args=()): display = self.find_free_display() log("starting test server on %s", display) server_args = ["--start=xterm"] + list(server_args) server = self.check_start_server(display, *server_args) xvfb1, client1 = self.run_client(display, *client_args) r = pollwait(client1, CLIENT_TIMEOUT) assert r is None, "client1 exited with code %s" % EXIT_STR.get(r, r) xvfb2, client2 = self.run_client(display, *client_args) r = pollwait(client2, CLIENT_TIMEOUT) assert r is None, "client2 exited with code %s" % EXIT_STR.get(r, r) if disconnect: #starting a second client should disconnect the first when not sharing assert pollwait(client1, 2) is not None, "the first client should have been disconnected" #killing the Xvfb should kill the client xvfb1.terminate() xvfb2.terminate() assert pollwait(xvfb1, CLIENT_TIMEOUT) is not None assert pollwait(xvfb2, CLIENT_TIMEOUT) is not None assert pollwait(client1, CLIENT_TIMEOUT) is not None assert pollwait(client2, CLIENT_TIMEOUT) is not None server.terminate()
def proc_exit(*args): log("proc_exit%s", args) c = proc.poll() if key in self.clients_disconnecting: self.clients_disconnecting.remove(key) elif c not in (0, None): self.warning.set_text(EXIT_STR.get(c, "exit code %s" % c).replace("_", " ")) try: del self.clients[key] except: pass else: def update(): self.update() self.populate() glib.idle_add(update)
def check_server(self, subcommand, display, *args): cmd = [subcommand] if display: cmd.append(display) if not WIN32: cmd += ["--no-daemon"] cmd += list(args) server_proc = self.run_xpra(cmd) if pollwait(server_proc, SERVER_TIMEOUT) is not None: self.show_proc_error(server_proc, "server failed to start") if display: #wait until the socket shows up: for _ in range(20): live = self.dotxpra.displays() if display in live: break time.sleep(1) if server_proc.poll() is not None: self.show_proc_error(server_proc, "server terminated") assert display in live, "server display '%s' not found in live displays %s" % ( display, live) #then wait a little before using it: time.sleep(1) #query it: version = None for _ in range(20): if version is None: args = ["version"] if display: args.append(display) version = self.run_xpra(args) r = pollwait(version, 1) log("version for %s returned %s", display, r) if r is not None: if r == 1: #re-run it version = None continue break time.sleep(1) if r != 0: self.show_proc_error( version, "version check failed for %s, returned %s" % (display, EXIT_STR.get(r, r))) return server_proc
def show_selected_session(self): #show this session: try: self.cleanup() proc = self.do_run_subcommand("top") exit_code = proc.wait() txt = "top subprocess terminated" attr = 0 if exit_code!=0: attr = curses.color_pair(RED) txt += " with error code %i" % exit_code if exit_code in EXIT_STR: txt += " (%s)" % EXIT_STR.get(exit_code, "").replace("_", " ") elif (exit_code-128) in SIGNAMES: #pylint: disable=superfluous-parens txt += " (%s)" % SIGNAMES[exit_code-128] self.message = monotonic_time(), txt, attr finally: self.stdscr = curses_init()
def estr(r): s = EXIT_STR.get(r) if s: return "%s : %s" % (r, s) return str(r)
def proc_exit(*args): log("proc_exit%s", args) c = proc.poll() if c not in (0, None): self.warning.set_text( EXIT_STR.get(c, "exit code %s" % c).replace("_", " "))
def _test(self, subcommand, options): log("starting test server with options=%s", options) args = ["--%s=%s" % (k, v) for k, v in options.items()] tcp_port = None xvfb = None if WIN32 or OSX: display = "" connect_args = [] elif self.display: display = self.display connect_args = [display] args.append("--use-display=yes") else: display = self.find_free_display() connect_args = [display] if subcommand == "shadow": xvfb = self.start_Xvfb(display) if TEST_RFB or WIN32: tcp_port = get_free_tcp_port() args += ["--bind-tcp=0.0.0.0:%i" % tcp_port] if WIN32: connect_args = ["tcp://127.0.0.1:%i" % tcp_port] server = None client = None rfb_client = None gui_client = None try: log("args=%s", " ".join("'%s'" % x for x in args)) server = self.check_server(subcommand, display, *args) #we should always be able to get the version: client = self.run_xpra(["version"] + connect_args) assert pollwait( client, 5 ) == 0, "version client failed to connect to server with args=%s" % args #run info query: cmd = ["info"] + connect_args client = self.run_xpra(cmd) r = pollwait(client, 20) assert r==0, "info client failed and returned %s: '%s' for server with args=%s" % \ (r, EXIT_STR.get(r, r), args) client_kwargs = {} if not (WIN32 or OSX): env = self.get_run_env() env["DISPLAY"] = self.client_display client_kwargs = {"env": env} if subcommand in ("shadow", "start-desktop") and TEST_RFB and options.get( "windows", True): vncviewer = which("vncviewer") log("testing RFB clients with vncviewer '%s'", vncviewer) if vncviewer: rfb_cmd = [vncviewer, "localhost::%i" % tcp_port] rfb_client = self.run_command(rfb_cmd, **client_kwargs) r = pollwait(rfb_client, 10) if r is not None: self.show_proc_error( rfb_client, "rfb client terminated early and returned %i for server with args=%s" % (r, args)) #connect a gui client: if WIN32 or (self.client_display and self.client_xvfb): xpra_args = [ "attach", "--clipboard=no", #could create loops "--notifications=no", #may get sent to the desktop session running the tests! ] + connect_args gui_client = self.run_xpra(xpra_args, **client_kwargs) r = pollwait(gui_client, 10) if r is not None: self.show_proc_error( gui_client, "gui client terminated early and returned %i : '%s' for server with args=%s" % (r, EXIT_STR.get(r, r), args)) if self.display: self.stop_server(server, "exit", *connect_args) else: self.stop_server(server, "stop", *connect_args) if display: if display in self.dotxpra.displays(): log.warn( "server socket for display %s should have been removed", display) if gui_client: r = pollwait(gui_client, 20) if r is None: log.warn("client still connected!") self.show_proc_pipes(server) raise Exception("gui client should have been disconnected") except Exception: log.error("test error for '%s' subcommand with options=%s", subcommand, options) raise finally: for x in (xvfb, rfb_client, gui_client, server, client): try: if x and x.poll() is None: x.terminate() except OSError: log("%s.terminate()", exc_info=True)