From 0f24cb494bf0e4e463f2588c601afb5c0186f128 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 9 May 2016 11:34:52 +0000 Subject: [PATCH] support absolute paths as arguments for the mmap command line option when attaching git-svn-id: https://xpra.org/svn/Xpra/trunk@12542 3bb7dfac-3a0b-4e04-842a-767bc560f471 --- src/man/xpra.1 | 6 ++- src/xpra/client/ui_client_base.py | 17 ++++++--- src/xpra/net/mmap_pipe.py | 61 ++++++++++++++++++++----------- src/xpra/scripts/config.py | 4 +- src/xpra/server/server_base.py | 2 +- 5 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/man/xpra.1 b/src/man/xpra.1 index 2188f3c4fa..24c5fbc69d 100644 --- a/src/man/xpra.1 +++ b/src/man/xpra.1 @@ -70,7 +70,7 @@ xpra \- viewer for remote, persistent X applications \fBxpra\fP \fBattach\fP [\fI:DISPLAY\fP | \fIssh:[USER@]HOST:DISPLAY\fP | \fItcp:[USER@]HOST:PORT[:DISPLAY]\fP] [\fB\-zLEVEL | \-\-compress\fP=\fILEVEL\fP] -[\fB\-\-mmap\fP=\fIyes\fP|\fIno\fP] +[\fB\-\-mmap\fP=\fIyes\fP|\fIno\fP|ABSOLUTEFILENAME] [\fB\-\-windows\fP=\fIyes\fP|\fIno\fP] [\fB\-\-clipboard\fP=\fIyes\fP|\fIno\fP] [\fB\-\-cursors\fP=\fIyes\fP|\fIno\fP] @@ -427,12 +427,14 @@ Displays a summary of command line usage. Enable debug logging. The special value \fBall\fP enables all debugging. .TP -\fB\-\-mmap\fP=\fIyes\fP|\fIno\fP +\fB\-\-mmap\fP=\fIyes\fP|\fIno\fP|\fIABSOLUTEFILENAME\fP Enable or disable memory mapped pixel data transfer. By default it is normally enabled automatically if the server and the client reside on the same filesystem namespace. This method of data transfer offers much lower overheads and reduces both CPU consumption and local network traffic. +When attaching, you can also specify an absolute path where +the mmap file will be created. .TP \fB\-\-windows\fP=\fIyes\fP|\fIno\fP Enable or disable the forwarding of windows. This is usually diff --git a/src/xpra/client/ui_client_base.py b/src/xpra/client/ui_client_base.py index 842aab4183..1db26c6486 100644 --- a/src/xpra/client/ui_client_base.py +++ b/src/xpra/client/ui_client_base.py @@ -315,8 +315,13 @@ def init(self, opts): self.dpi = int(opts.dpi) self.xsettings_enabled = opts.xsettings - self.supports_mmap = MMAP_SUPPORTED and opts.mmap - self.mmap_group = opts.mmap_group + if MMAP_SUPPORTED: + self.mmap_group = opts.mmap_group + if os.path.isabs(opts.mmap): + self.mmap_filename = opts.mmap + self.supports_mmap = True + else: + self.supports_mmap = opts.mmap.lower() in TRUE_OPTIONS self.shadow_fullscreen = opts.shadow_fullscreen self.webcam_option = opts.webcam @@ -464,7 +469,7 @@ def show_tray(*args): def setup_connection(self, conn): XpraClientBase.setup_connection(self, conn) if self.supports_mmap: - self.init_mmap(self.mmap_group, conn.filename) + self.init_mmap(self.mmap_filename, self.mmap_group, conn.filename) def parse_border(self, border_str, extra_args): @@ -1084,8 +1089,8 @@ def window_bell(self, window, device, percent, pitch, duration, bell_class, bell raise Exception("override me!") - def init_mmap(self, mmap_group, socket_filename): - log("init_mmap(%s, %s)", mmap_group, socket_filename) + def init_mmap(self, mmap_filename, mmap_group, socket_filename): + log("init_mmap(%s, %s, %s)", mmap_filename, mmap_group, socket_filename) from xpra.os_util import get_int_uuid from xpra.net.mmap_pipe import init_client_mmap #calculate size: @@ -1095,7 +1100,7 @@ def init_mmap(self, mmap_group, socket_filename): mmap_size = min(1024*1024*1024, mmap_size) self.mmap_token = get_int_uuid() self.mmap_enabled, self.mmap, self.mmap_size, self.mmap_tempfile, self.mmap_filename = \ - init_client_mmap(self.mmap_token, mmap_group, socket_filename, mmap_size) + init_client_mmap(self.mmap_token, mmap_group, socket_filename, mmap_size, self.mmap_filename) def clean_mmap(self): log("XpraClient.clean_mmap() mmap_filename=%s", self.mmap_filename) diff --git a/src/xpra/net/mmap_pipe.py b/src/xpra/net/mmap_pipe.py index 1bc5c3cafa..26512a03f0 100644 --- a/src/xpra/net/mmap_pipe.py +++ b/src/xpra/net/mmap_pipe.py @@ -21,36 +21,51 @@ def roundup(n, m): return (n + m - 1) & ~(m - 1) -def init_client_mmap(token, mmap_group=None, socket_filename=None, size=128*1024*1024): +def init_client_mmap(token, mmap_group=None, socket_filename=None, size=128*1024*1024, filename=None): """ Initializes an mmap area, writes the token in it and returns: (success flag, mmap_area, mmap_size, temp_file, mmap_filename) The caller must keep hold of temp_file to ensure it does not get deleted! This is used by the client. """ + def rerr(): + return False, None, 0, None, None if not can_use_mmap(): log.error("cannot use mmap: python version is too old?") - return False, None, 0, None, None - log("init_mmap(%s, %s, %s)", token, mmap_group, socket_filename) + return rerr() + log("init_mmap%s", (token, mmap_group, socket_filename, size, filename)) try: import mmap - import tempfile - from stat import S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP - mmap_dir = os.getenv("TMPDIR", "/tmp") - if not os.path.exists(mmap_dir): - raise Exception("TMPDIR %s does not exist!" % mmap_dir) - #create the mmap file, the mkstemp that is called via NamedTemporaryFile ensures - #that the file is readable and writable only by the creating user ID - try: - temp = tempfile.NamedTemporaryFile(prefix="xpra.", suffix=".mmap", dir=mmap_dir) - except OSError as e: - log.error("Error: cannot create mmap file:") - log.error(" %s", e) - return False, None, 0, None, None - #keep a reference to it so it does not disappear! - mmap_temp_file = temp - mmap_filename = temp.name - fd = temp.file.fileno() + if filename: + import errno + flags = os.O_CREAT | os.O_EXCL | os.O_RDWR + try: + fd = os.open(filename, flags) + mmap_temp_file = None #os.fdopen(fd, 'w') + mmap_filename = filename + except OSError as e: + if e.errno == errno.EEXIST: + log.error("Error: the mmap file '%s' already exists", filename) + return rerr() + raise + else: + import tempfile + from stat import S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP + mmap_dir = os.getenv("TMPDIR", "/tmp") + if not os.path.exists(mmap_dir): + raise Exception("TMPDIR %s does not exist!" % mmap_dir) + #create the mmap file, the mkstemp that is called via NamedTemporaryFile ensures + #that the file is readable and writable only by the creating user ID + try: + temp = tempfile.NamedTemporaryFile(prefix="xpra.", suffix=".mmap", dir=mmap_dir) + except OSError as e: + log.error("Error: cannot create mmap file:") + log.error(" %s", e) + return rerr() + #keep a reference to it so it does not disappear! + mmap_temp_file = temp + mmap_filename = temp.name + fd = temp.file.fileno() #set the group permissions and gid if the mmap-group option is specified if mmap_group and type(socket_filename)==str and os.path.exists(socket_filename): s = os.stat(socket_filename) @@ -69,9 +84,11 @@ def init_client_mmap(token, mmap_group=None, socket_filename=None, size=128*1024 write_mmap_token(mmap_area, token) return True, mmap_area, mmap_size, mmap_temp_file, mmap_filename except Exception as e: - log.error("failed to setup mmap: %s", e, exc_info=True) + log("failed to setup mmap: %s", e, exc_info=True) + log.error("Error: mmap setup failed:") + log.error(" %s", e) clean_mmap(mmap_filename) - return False, None, 0, None, None + return rerr() def clean_mmap(mmap_filename): log("clean_mmap(%s)", mmap_filename) diff --git a/src/xpra/scripts/config.py b/src/xpra/scripts/config.py index 765ef5bed2..07f71541eb 100755 --- a/src/xpra/scripts/config.py +++ b/src/xpra/scripts/config.py @@ -294,6 +294,7 @@ def read_xpra_defaults(): "ssh" : str, "xvfb" : str, "socket-dir" : str, + "mmap" : str, "log-dir" : str, "log-file" : str, "border" : str, @@ -341,7 +342,6 @@ def read_xpra_defaults(): "tray" : bool, "pulseaudio" : bool, "dbus-proxy" : bool, - "mmap" : bool, "mmap-group" : bool, "readonly" : bool, "keyboard-sync" : bool, @@ -517,7 +517,7 @@ def addtrailingslash(v): "tray" : True, "pulseaudio" : not OSX and not WIN32, "dbus-proxy" : not OSX and not WIN32, - "mmap" : not OSX and not WIN32, + "mmap" : ["off", "on"][not OSX and not WIN32], "mmap-group" : False, "speaker" : ["disabled", "on"][has_sound_support], "microphone" : ["disabled", "off"][has_sound_support], diff --git a/src/xpra/server/server_base.py b/src/xpra/server/server_base.py index 3b07de9608..3e54722327 100644 --- a/src/xpra/server/server_base.py +++ b/src/xpra/server/server_base.py @@ -212,7 +212,7 @@ def init(self, opts): self.init_options(opts) def init_options(self, opts): - self.supports_mmap = opts.mmap + self.supports_mmap = opts.mmap.lower() in TRUE_OPTIONS self.allowed_encodings = opts.encodings self.init_encoding(opts.encoding)