xpra icon
Bug tracker and wiki

Ticket #1535: displayfd-v6.patch

File displayfd-v6.patch, 14.3 KB (added by Antoine Martin, 18 months ago)

work in progress - doesn't like daemon=yes

  • xpra/scripts/config.py

     
    515515                    "ssl-server-hostname" : str,
    516516                    "ssl-options"       : str,
    517517                    #int options:
     518                    "displayfd"         : int,
    518519                    "pings"             : int,
    519520                    "quality"           : int,
    520521                    "min-quality"       : int,
     
    899900                    "microphone"        : ["disabled", "off"][has_sound_support()],
    900901                    "readonly"          : False,
    901902                    "keyboard-sync"     : True,
     903                    "displayfd"         : 0,
    902904                    "pings"             : 5,
    903905                    "cursors"           : True,
    904906                    "bell"              : True,
  • xpra/scripts/main.py

     
    505505                          default=defaults.xvfb,
    506506                          metavar="CMD",
    507507                          help="How to run the headless X server. Default: '%default'.")
     508        group.add_option("--displayfd", action="store", metavar="FD",
     509                          dest="displayfd", default=defaults.displayfd,
     510                          help="The xpra server will write the display number back on this file descriptor as a newline-terminated string.")
    508511        group.add_option("--fake-xinerama", action="store", metavar="yes|no",
    509512                          dest="fake_xinerama",
    510513                          default=defaults.fake_xinerama,
    511514                          help="Setup fake xinerama support for the session. Default: %s." % enabled_str(defaults.fake_xinerama))
    512515    else:
    513         ignore({"use-display"   : defaults.use_display,
    514                 "xvfb"          : defaults.xvfb,
    515                 "fake-xinerama" : defaults.fake_xinerama})
     516        ignore({
     517            "use-display"   : defaults.use_display,
     518            "xvfb"          : defaults.xvfb,
     519            "displayfd"     : defaults.displayfd,
     520            "fake-xinerama" : defaults.fake_xinerama,
     521            })
    516522    group.add_option("--resize-display", action="store",
    517523                      dest="resize_display", default=defaults.resize_display, metavar="yes|no",
    518524                      help="Whether the server display should be resized to match the client resolution. Default: %s." % enabled_str(defaults.resize_display))
     
    26902696            proc.wait()
    26912697        proc = None
    26922698    else:
    2693         cmd.append("--systemd-run=no")
    2694         cmd.append("--daemon=yes")
    26952699        #useful for testing failures that cause the whole XDG_RUNTIME_DIR to get nuked
    26962700        #(and the log file with it):
    26972701        #cmd.append("--log-file=/tmp/proxy.log")
    2698         if POSIX and getuid()==0 and (uid!=0 or gid!=0):
    2699             cmd.append("--uid=%i" % uid)
    2700             cmd.append("--gid=%i" % gid)
     2702        if POSIX:
     2703            cmd.append("--daemon=yes")
     2704            cmd.append("--systemd-run=no")
     2705            if getuid()==0 and (uid!=0 or gid!=0):
     2706                cmd.append("--uid=%i" % uid)
     2707                cmd.append("--gid=%i" % gid)
     2708            r_pipe, w_pipe = os.pipe()
     2709            cmd.append("--displayfd=%s" % w_pipe)
     2710            close_fds = False
     2711            def preexec_fn():
     2712                from xpra.os_util import close_fds as osclose_fds
     2713                osclose_fds([0, 1, 2, r_pipe, w_pipe])
     2714        else:
     2715            close_fds = True
     2716            preexec_fn = None
    27012717        log("start_server_subprocess: command=%s", csv(["'%s'" % x for x in cmd]))
    2702         proc = Popen(cmd, shell=False, close_fds=True, env=env, cwd=cwd)
     2718        proc = Popen(cmd, shell=False, close_fds=close_fds, env=env, cwd=cwd, preexec_fn=preexec_fn)
    27032719        log("proc=%s", proc)
     2720        if POSIX:
     2721            from xpra.server.server_util import read_displayfd, parse_displayfd
     2722            buf = read_displayfd(r_pipe, proc=proc)
     2723            log.info("read_displayfd(%i)=%s", r_pipe, buf)
     2724            os.close(r_pipe)
     2725            os.close(w_pipe)
     2726            def displayfd_err(msg):
     2727                log.error("Error: displayfd failed")
     2728                log.error(" %s", msg)
     2729            n = parse_displayfd(buf, displayfd_err)
     2730            matching_display = ":%s" % n
     2731            log("matching display=%s", matching_display)
    27042732    socket_path, display = identify_new_socket(proc, dotxpra, existing_sockets, matching_display, new_server_uuid, display_name, uid)
    27052733    return proc, socket_path, display
    27062734
  • xpra/scripts/server.py

     
    656656        os.environ.update(protected_env)
    657657        if display_name!=odisplay_name and pam:
    658658            pam.set_items({"XDISPLAY" : display_name})
     659    if POSIX and opts.displayfd:
     660        from xpra.server.server_util import write_displayfd
     661        try:
     662            displayfd = int(opts.displayfd)
     663            display = display_name[1:]
     664            log.info("writing display='%s' to displayfd=%i", display, displayfd)
     665            assert write_displayfd(displayfd, display), "timeout"
     666            log.info("closing fd=%s", displayfd)
     667            #os.fsync(displayfd)
     668            os.close(displayfd)
     669        except Exception as e:
     670            log.error("write_displayfd failed", exc_info=True)
     671            log.error("Error: failed to write '%s' to fd=%s", display_name, opts.displayfd)
     672            log.error(" %s", str(e) or type(e))
    659673
    660674    close_display = None
    661675    if not proxying:
  • xpra/server/server_util.py

     
    66import sys
    77import os.path
    88
    9 from xpra.os_util import OSX, POSIX, shellsub, getuid, getgid
     9from xpra.util import nonl
     10from xpra.os_util import OSX, POSIX, shellsub, getuid, getgid, monotonic_time
    1011from xpra.platform.dotxpra import osexpand, norm_makepath
    1112from xpra.scripts.config import InitException
    1213
     
    359360
    360361def create_input_devices(uid, gid=-1):
    361362    return create_uinput_devices(uid, gid)
     363
     364
     365def write_displayfd(w_pipe, display, timeout=10):
     366    import select   #@UnresolvedImport
     367    buf = b"%s\n" % display
     368    limit = monotonic_time()+timeout
     369    while buf and monotonic_time()<limit:
     370        _, w, _ = select.select([], [w_pipe], [], max(0, limit-monotonic_time()))
     371        if w_pipe in w:
     372            count = os.write(w_pipe, buf)
     373            buf = buf[count:]
     374    return len(buf)==0
     375
     376def read_displayfd(r_pipe, timeout=10, proc=None):
     377    import select   #@UnresolvedImport
     378    # Read the display number from the pipe we gave to Xvfb
     379    # waiting up to 10 seconds for it to show up
     380    limit = monotonic_time()+timeout
     381    buf = b""
     382    while monotonic_time()<limit and len(buf)<8 and (proc is None or proc.poll() is None):
     383        r, _, _ = select.select([r_pipe], [], [], max(0, limit-monotonic_time()))
     384        if r_pipe in r:
     385            buf += os.read(r_pipe, 8)
     386            if buf[-1] == b'\n':
     387                break
     388    return buf
     389
     390def parse_displayfd(buf, err):
     391    if len(buf) == 0:
     392        err("did not provide a display number using displayfd")
     393    if buf[-1] != '\n':
     394        err("output not terminated by newline: %s" % buf)
     395    try:
     396        n = int(buf[:-1])
     397    except:
     398        err("display number is not a valid number: %s" % buf[:-1])
     399    if n<0 or n>=2**16:
     400        err("provided an invalid display number: %s" % n)
     401    return n
  • xpra/x11/vfb_util.py

     
    1313import os.path
    1414
    1515from xpra.scripts.config import InitException, get_Xdummy_confdir
    16 from xpra.os_util import setsid, shellsub, monotonic_time, close_fds, setuidgid, getuid, getgid, strtobytes, POSIX
     16from xpra.os_util import setsid, shellsub, close_fds, setuidgid, getuid, getgid, strtobytes, POSIX
     17from xpra.server.server_util import read_displayfd, parse_displayfd
    1718
    1819
    1920DEFAULT_VFB_RESOLUTION = tuple(int(x) for x in os.environ.get("XPRA_DEFAULT_VFB_RESOLUTION", "8192x4096").replace(",", "x").split("x", 1))
     
    153154            tmp_xorg_log_file = xvfb_cmd[logfile_argindex+1]
    154155        #make sure the Xorg log directory exists:
    155156        xorg_log_dir = os.path.dirname(pathexpand(xvfb_cmd[logfile_argindex+1]))
    156         log("xorg_log_dir=%s - exists=%s", xorg_log_dir, os.path.exists(xorg_log_dir))
    157157        if not os.path.exists(xorg_log_dir):
    158158            try:
    159159                log("creating Xorg log dir '%s'", xorg_log_dir)
     
    168168
    169169    #apply string substitutions:
    170170    xvfb_cmd = pathexpand(xvfb_str).split()
     171    log("shellsub(%s, %s)=%s", xvfb_str, subs, xvfb_cmd)
    171172
    172173    if not xvfb_cmd:
    173174        raise InitException("cannot start Xvfb, the command definition is missing!")
     
    176177        xvfb_cmd.append("-depth")
    177178        xvfb_cmd.append(str(pixel_depth))
    178179    if use_display_fd:
    179         # 'S' means that we allocate the display automatically
    180180        r_pipe, w_pipe = os.pipe()
    181181        xvfb_cmd += ["-displayfd", str(w_pipe)]
    182182        xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, display_name)
    183183        def preexec():
    184184            setsid()
    185             if POSIX and getuid()==0 and uid:
     185            if getuid()==0 and uid:
    186186                setuidgid(uid, gid)
    187187            close_fds([0, 1, 2, r_pipe, w_pipe])
    188188        log("xvfb_cmd=%s", xvfb_cmd)
     
    189189        xvfb = subprocess.Popen(xvfb_cmd, executable=xvfb_executable, close_fds=False,
    190190                                stdin=subprocess.PIPE, preexec_fn=preexec, cwd=cwd)
    191191        # Read the display number from the pipe we gave to Xvfb
    192         # waiting up to 10 seconds for it to show up
    193         limit = monotonic_time()+10
    194         buf = ""
    195         import select   #@UnresolvedImport
    196         while monotonic_time()<limit and len(buf)<8:
    197             r, _, _ = select.select([r_pipe], [], [], max(0, limit-monotonic_time()))
    198             if r_pipe in r:
    199                 buf += os.read(r_pipe, 8)
    200                 if buf[-1] == '\n':
    201                     break
     192        buf = read_displayfd(r_pipe)
    202193        os.close(r_pipe)
    203194        os.close(w_pipe)
    204         if len(buf) == 0:
    205             raise InitException("%s did not provide a display number using -displayfd" % xvfb_executable)
    206         if buf[-1] != '\n':
    207             raise InitException("%s output not terminated by newline: %s" % (xvfb_executable, buf))
    208         try:
    209             n = int(buf[:-1])
    210         except:
    211             raise InitException("%s display number is not a valid number: %s" % (xvfb_executable, buf[:-1]))
    212         if n<0 or n>=2**16:
    213             raise InitException("%s provided an invalid display number: %s" % (xvfb_executable, n))
     195        def displayfd_err(msg):
     196            raise InitException("%s: %s" % (xvfb_executable, msg))
     197        n = parse_displayfd(buf, displayfd_err)
    214198        new_display_name = ":%s" % n
    215199        log("Using display number provided by %s: %s", xvfb_executable, new_display_name)
    216200        if tmp_xorg_log_file != None:
  • man/xpra.1

     
    6161[\fB\-\-sharing\fP=\fIyes\fP|\fIno\fP]
    6262[\fB\-\-bind\fP=\fIBIND_LOCATION\fP]
    6363[\fB\-\-bind\-tcp\fP=\fI[HOST]:PORT\fP]
     64[\fB\-\-bind\-ws\fP=\fI[HOST]:PORT\fP]
     65[\fB\-\-bind\-wss\fP=\fI[HOST]:PORT\fP]
    6466[\fB\-\-bind\-ssl\fP=\fI[HOST]:PORT\fP]
    6567[\fB\-\-bind\-vsock\fP=\fICID:PORT\fP]
    6668[\fB\-\-encryption\fP=\fICIPHER\fP]
     
    189191[\fB\-\-microphone\-codec\fP=\fICODEC\fP]
    190192[\fB\-\-bind\fP=\fISOCKET|DIRECTORY\fP]
    191193[\fB\-\-bind\-tcp\fP=\fI[HOST]:PORT\fP]
     194[\fB\-\-bind\-ws\fP=\fI[HOST]:PORT\fP]
     195[\fB\-\-bind\-wss\fP=\fI[HOST]:PORT\fP]
    192196[\fB\-\-bind\-ssl\fP=\fI[HOST]:PORT\fP]
    193197[\fB\-\-bind\-vsock\fP=\fICID:PORT\fP]
    194198[\fB\-\-auth\fP=\fIMODULE\fP]
     
    427431\fIsocket\-dirs\fP).
    428432
    429433If the xpra server was given the \fB\-\-bind\-tcp\fP, \fB\-\-bind\-ssl\fP
    430 or \fB\-\-bind\-vsock\fP option when started then you can also connect
    431 to it using a display of the form \fBtcp:HOST:PORT\fP, \fBssl:HOST:PORT\fP
    432 or \fBvsock:HOST:PORT\fP.
     434\fB\-\-bind\-ws\fP, \fB\-\-bind\-wss\fP or \fB\-\-bind\-vsock\fP option
     435when started then you can also connect
     436to it using a display of the form \fBtcp:HOST:PORT\fP, \fBssl:HOST:PORT\fP,
     437\fBws:HOST:PORT\fP, \fBwss:HOST:PORT\fP or \fBvsock:HOST:PORT\fP.
    433438(Notice that \fBssh:\fP takes an optional \fIdisplay\fP number,
    434439while those take a required \fIport\fP number.)
    435440.\" --------------------------------------------------------------------
     
    731736Using this switch without using the \fItcp\-auth\fP option is not recommended,
    732737and is a major security risk (especially when passing 0.0.0.0)!
    733738Anyone at all may connect to this port and access your session.
     739
     740TCP sockets may also process HTTP / Websocket connections
     741if the \fBhtml\fP switch is enabled.
     742TCP sockets may also be upgraded to SSL sockets if the
     743\fBssl\fP switch is enabled.
    734744.TP
     745\fB\-\-bind\-ws\fP=\fI[HOST]:PORT\fP
     746Create an HTTP / Websocket listener.
     747See \fBbind\-tcp\fP for host restrictions,
     748you should use the \fBauth\-ws\fP to secure access.
     749.TP
     750\fB\-\-bind\-wss\fP=\fI[HOST]:PORT\fP
     751Create an HTTPS / Secure Websocket listener.
     752See \fBbind\-tcp\fP for host restrictions,
     753you should use the \fBauth\-wss\fP to secure access.
     754.TP
    735755\fB\-\-bind\-ssl\fP=\fI[HOST]:PORT\fP
    736756Just like \-\-bind-\-tcp\fP but for SSL sockets.
    737757See \fIssl\-auth\fP and the other SSL options.
     
    821841Just like the \fBauth\fP switch, except this one only applies
    822842to TCP sockets (sockets defined using the \fBbind\-tcp\fP switch).
    823843.TP
     844\fB\-\-ws\-auth\fP=\fIMODULE\fP
     845Just like the \fBauth\fP switch, except this one only applies
     846to ws sockets (sockets defined using the \fBbind\-ws\fP switch).
     847.TP
     848\fB\-\-wss\-auth\fP=\fIMODULE\fP
     849Just like the \fBauth\fP switch, except this one only applies
     850to wss sockets (sockets defined using the \fBbind\-wss\fP switch).
     851.TP
    824852\fB\-\-ssl\-auth\fP=\fIMODULE\fP
    825853Just like the \fBauth\fP switch, except this one only applies
    826854to SSL sockets: sockets defined using the \fBbind\-ssl\fP switch,