Ticket #88: share-mmap-v2.patch
File share-mmap-v2.patch, 12.6 KB (added by , 9 years ago) |
---|
-
xpra/server.py
798 798 log.error("too many connections (%s), ignoring new one", len(self._potential_protocols)) 799 799 listener.close() 800 800 return True 801 sock, _= listener.accept()802 protocol = Protocol(SocketConnection(sock ), self.process_packet)801 sock, address = listener.accept() 802 protocol = Protocol(SocketConnection(sock, address), self.process_packet) 803 803 self._potential_protocols.append(protocol) 804 804 def verify_connection_accepted(protocol): 805 805 if not protocol._closed and protocol in self._potential_protocols and protocol!=self._protocol: -
xpra/client.py
434 434 import tempfile 435 435 import uuid 436 436 import ctypes 437 from stat import S_IRUSR,S_IWUSR 437 from stat import S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP 438 438 mmap_dir = os.getenv("TMPDIR", "/tmp") 439 439 if not os.path.exists(mmap_dir): 440 440 raise Exception("TMPDIR %s does not exist!" % mmap_dir) … … 442 442 #keep a reference to it so it does not disappear! 443 443 self._mmap_temp_file = temp 444 444 self.mmap_file = temp.name 445 #ensure that the permissions are strict: 446 os.chmod(self.mmap_file, S_IRUSR|S_IWUSR) 445 fd = temp.file.fileno() 446 #ensure that the permissions are strict or set mmap-group option: 447 if opts.mmap_group and type(conn.target)==str and os.path.exists(conn.target): 448 s = os.stat(conn.target) 449 os.fchown(fd, -1, s.st_gid) 450 os.fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) 451 else: 452 os.fchmod(fd, S_IRUSR|S_IWUSR) 447 453 self.mmap_size = max(4096, mmap.PAGESIZE)*32*1024 #generally 128MB 448 fd = temp.file.fileno()449 454 log("using mmap file %s, fd=%s, size=%s", self.mmap_file, fd, self.mmap_size) 450 455 os.lseek(fd, self.mmap_size-1, os.SEEK_SET) 451 456 assert os.write(fd, '\x00') -
xpra/dotxpra.py
15 15 pass 16 16 17 17 class DotXpra(object): 18 def __init__(self, dir=None):18 def __init__(self, sockdir=None, confdir=None): 19 19 assert XPRA_LOCAL_SERVERS_SUPPORTED 20 if dir is None: 21 dir = os.path.expanduser("~/.xpra") 22 self._dir = dir 23 if not os.path.exists(self._dir): 24 os.mkdir(dir, 0700) 20 self._confdir = os.path.expanduser(confdir or "~/.xpra") 21 self._sockdir = os.path.expanduser(sockdir or "~/.xpra") 22 if not os.path.exists(self._confdir): 23 os.mkdir(self._confdir, 0700) 24 if not os.path.exists(self._sockdir): 25 os.mkdir(self._sockdir, 0700) 25 26 self._prefix = "%s-" % (socket.gethostname(),) 26 27 27 def dir(self):28 return self._ dir28 def confdir(self): 29 return self._confdir 29 30 30 31 def _normalize_local_display_name(self, local_display_name): 31 32 if not local_display_name.startswith(":"): … … 37 38 assert char in "0123456789" 38 39 return local_display_name 39 40 40 def socket_path(self, local_display_name):41 def make_path(self, local_display_name, dirpath ): 41 42 local_display_name = self._normalize_local_display_name(local_display_name) 42 return os.path.join( self._dir, self._prefix + local_display_name[1:])43 return os.path.join( dirpath , self._prefix + local_display_name[1:]) 43 44 45 def socket_path(self, local_display_name): 46 return self.make_path(local_display_name, self._sockdir) 47 48 def conf_path(self, local_display_name): 49 return self.make_path(local_display_name, self._confdir) 50 44 51 LIVE = "LIVE" 45 52 DEAD = "DEAD" 46 53 UNKNOWN = "UNKNOWN" … … 74 81 75 82 def sockets(self): 76 83 results = [] 77 base = os.path.join(self._ dir, self._prefix)84 base = os.path.join(self._sockdir, self._prefix) 78 85 potential_sockets = glob.glob(base + "*") 79 86 for path in potential_sockets: 80 87 if stat.S_ISSOCK(os.stat(path).st_mode): -
xpra/scripts/main.py
163 163 parser.add_option("--ssh", action="store", 164 164 dest="ssh", default=DEFAULT_SSH_CMD, metavar="CMD", 165 165 help="How to run ssh (default: '%default')") 166 parser.add_option("--socket-dir", action="store", 167 dest="sockdir", default="~/.xpra", 168 help="Directory to place socket file in (default: '%default')") 169 parser.add_option("--mmap-group", action="store_true", 170 dest="mmap_group", default=False, 171 help="Set the group permission on the mmap file to the same value as the owner of the server socket file we connect to when creating the mmap file with the client (default: '%default')") 166 172 parser.add_option("--remote-xpra", action="store", 167 173 dest="remote_xpra", default=".xpra/run-xpra", 168 174 metavar="CMD", … … 263 269 "type": "unix-domain", 264 270 "local": True, 265 271 "display": display_name, 272 "sockdir": opts.sockdir, 266 273 } 267 274 return desc 268 275 elif display_name.startswith("tcp:"): … … 284 291 if not XPRA_LOCAL_SERVERS_SUPPORTED: 285 292 parser.error("need to specify a display") 286 293 # Pick a default server 287 sockdir = DotXpra( )294 sockdir = DotXpra(opts.sockdir) 288 295 servers = sockdir.sockets() 289 296 live_servers = [display 290 297 for (state, display) in servers … … 305 312 sock.connect(target) 306 313 except socket.error, e: 307 314 sys.exit("Connection failed: %s" % (e,)) 308 return SocketConnection(sock )315 return SocketConnection(sock, target) 309 316 310 317 def connect_or_fail(display_desc): 311 318 if display_desc["type"] == "ssh": … … 324 331 from wimpiggy.util import gtk_main_quit_really 325 332 gtk_main_quit_really() 326 333 raise IOError(error_message) 327 return TwoFileConnection(child.stdin, child.stdout, abort_test )334 return TwoFileConnection(child.stdin, child.stdout, abort_test, target=cmd) 328 335 329 336 elif XPRA_LOCAL_SERVERS_SUPPORTED and display_desc["type"] == "unix-domain": 330 sockdir = DotXpra( )337 sockdir = DotXpra(display_desc["sockdir"]) 331 338 sock = socket.socket(socket.AF_UNIX) 332 return _socket_connect(sock,333 sockdir.socket_path(display_desc["display"]))339 sockfile = sockdir.socket_path(display_desc["display"]) 340 return _socket_connect(sock, sockfile) 334 341 335 342 elif display_desc["type"] == "tcp": 336 343 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 337 return _socket_connect(sock,338 (display_desc["host"], display_desc["port"]))344 tcp_endpoint = (display_desc["host"], display_desc["port"]) 345 return _socket_connect(sock, tcp_endpoint) 339 346 340 347 else: 341 348 assert False, "unsupported display type in connect" … … 405 412 while conn.read(4096): 406 413 pass 407 414 if display_desc["local"]: 408 sockdir = DotXpra( )415 sockdir = DotXpra(opts.sockdir) 409 416 for _ in xrange(6): 410 417 final_state = sockdir.server_state(display_desc["display"]) 411 418 if final_state is DotXpra.LIVE: 412 time.sleep(0.5)413 else:414 419 break 420 time.sleep(0.5) 415 421 if final_state is DotXpra.DEAD: 416 422 print("xpra at %s has exited." % display_desc["display"]) 417 423 sys.exit(0) … … 423 429 print("Failed to shutdown xpra at %s" % display_desc["display"]) 424 430 sys.exit(1) 425 431 else: 426 assert False 432 assert False, "invalid state: %s" % final_state 427 433 else: 428 434 print("Sent shutdown command") 429 435 … … 431 437 assert "gtk" not in sys.modules 432 438 if extra_args: 433 439 parser.error("too many arguments for mode") 434 sockdir = DotXpra( )440 sockdir = DotXpra(opts.sockdir) 435 441 results = sockdir.sockets() 436 442 if not results: 437 443 sys.stdout.write("No xpra sessions found\n") -
xpra/scripts/server.py
15 15 import atexit 16 16 import signal 17 17 import socket 18 import os 18 19 19 20 from xpra.wait_for_x_server import wait_for_x_server #@UnresolvedImport 20 21 from xpra.dotxpra import DotXpra, ServerSockInUse 21 22 23 from stat import S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP 24 22 25 _cleanups = [] 23 26 def run_cleanups(): 24 27 for c in _cleanups: … … 137 140 listener = socket.socket(socket.AF_UNIX) 138 141 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 139 142 listener.bind(sockpath) 143 os.chmod(sockpath, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) 140 144 return listener 141 145 142 146 def create_tcp_socket(parser, spec): … … 181 185 assert mode in ("start", "upgrade") 182 186 upgrading = (mode == "upgrade") 183 187 184 dotxpra = DotXpra( )188 dotxpra = DotXpra(opts.sockdir) 185 189 186 190 # This used to be given a display-specific name, but now we give it a 187 191 # single fixed name and if multiple servers are started then the last one … … 191 195 # is running on the remote host. Might need to revisit this later if 192 196 # people run into problems or autodiscovery turns out to be less useful 193 197 # than expected. 194 scriptpath = os.path.join(dotxpra. dir(), "run-xpra")198 scriptpath = os.path.join(dotxpra.confdir(), "run-xpra") 195 199 196 200 # Save the starting dir now, because we'll lose track of it when we 197 201 # daemonize: 198 202 starting_dir = os.getcwd() 199 203 200 204 clobber = upgrading or opts.use_display 205 try: 206 sockpath = dotxpra.server_socket_path(display_name, clobber) 207 except ServerSockInUse: 208 parser.error("You already have an xpra server running at %s\n" 209 " (did you want 'xpra upgrade'?)" 210 % (display_name,)) 201 211 # Daemonize: 202 212 if opts.daemon: 203 try: 204 logpath = dotxpra.server_socket_path(display_name, clobber) + ".log" 205 except ServerSockInUse: 206 parser.error("You already have an xpra server running at %s\n" 207 " (did you want 'xpra upgrade'?)" 208 % (display_name,)) 213 logpath = dotxpra.conf_path(display_name) + ".log" 209 214 sys.stderr.write("Entering daemon mode; " 210 215 + "any further errors will be reported to:\n" 211 216 + (" %s\n" % logpath)) … … 299 304 save_pid(xvfb_pid) 300 305 301 306 sockets = [] 302 sockpath = dotxpra.server_socket_path(display_name, clobber)303 307 #print("creating server socket %s" % sockpath) 304 308 sockets.append(create_unix_domain_socket(sockpath)) 305 309 def cleanup_socket(): -
xpra/protocol.py
27 27 # (os.read/os.write-style interface) two-way byte stream: 28 28 29 29 class TwoFileConnection(object): 30 def __init__(self, writeable, readable, abort_test=None ):30 def __init__(self, writeable, readable, abort_test=None, target=None): 31 31 self._writeable = writeable 32 32 self._readable = readable 33 33 self._abort_test = abort_test 34 self.target = target 34 35 35 36 def may_abort(self, action): 36 37 """ if abort_test is defined, run it """ … … 49 50 self._writeable.close() 50 51 self._readable.close() 51 52 53 def __str__(self): 54 return "TwoFileConnection(%s)" % str(self.target) 55 52 56 class SocketConnection(object): 53 def __init__(self, s ):57 def __init__(self, s, target): 54 58 self._s = s 59 self.target = target 55 60 56 61 def read(self, n): 57 62 return self._s.recv(n) … … 61 66 62 67 def close(self): 63 68 return self._s.close() 64 69 70 def __str__(self): 71 return "SocketConnection(%s)" % str(self.target) 72 65 73 def repr_ellipsized(obj, limit=100): 66 74 if isinstance(obj, str) and len(obj) > limit: 67 75 return repr(obj[:limit]) + "..."