コード例 #1
0
ファイル: server.py プロジェクト: rudresh2319/Xpra
def run_server(error_cb, opts, mode, xpra_file, extra_args):
    try:
        cwd = os.getcwd()
    except:
        cwd = os.path.expanduser("~")
        sys.stderr.write(
            "current working directory does not exist, using '%s'\n" % cwd)
    if opts.encoding and opts.encoding == "help":
        #avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        #disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging
        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase
        sb = ServerBase()
        sb.init(opts)
        #ensures that the threaded video helper init has completed
        #(by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help
        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying = mode == "proxy"
    clobber = upgrading or opts.use_display

    #get the display name:
    if shadowing and len(extra_args) == 0:
        if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
            #just a virtual name for the only display available:
            display_name = ":0"
        else:
            from xpra.scripts.main import guess_X11_display
            display_name = guess_X11_display(opts.socket_dir)
    elif upgrading and len(extra_args) == 0:
        from xpra.scripts.main import guess_xpra_display
        display_name = guess_xpra_display(opts.socket_dir)
    else:
        if len(extra_args) > 1:
            error_cb(
                "too many extra arguments: only expected a display number")
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not proxying:
                display_name_check(display_name)
        else:
            if proxying:
                error_cb(
                    "you must specify a free virtual display name to use with the proxy server"
                )
            if not opts.displayfd:
                error_cb(
                    "displayfd support is not enabled on this system, you must specify the display to use"
                )
            if opts.use_display:
                #only use automatic guess for xpra displays and not X11 displays:
                from xpra.scripts.main import guess_xpra_display  #@Reimport
                display_name = guess_xpra_display(opts.socket_dir)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = 'S' + str(os.getpid())

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        error_cb(
            "--exit-with-children specified without any children to spawn; exiting immediately"
        )

    atexit.register(run_cleanups)
    #the server class will usually override those:
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    dotxpra = DotXpra(opts.socket_dir)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if opts.daemon:
        #daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)
        # At this point we may not know the display name,
        # so log_filename0 may point to a temporary file which we will rename later
        log_filename0 = select_log_file(dotxpra, opts.log_file, display_name)
        logfd = open_log_file(log_filename0)
        assert logfd > 2
        stdout, stderr = daemonize(logfd)
        try:
            stderr.write("Entering daemon mode; " +
                         "any further errors will be reported to:\n" +
                         ("  %s\n" % log_filename0))
        except:
            #this can happen if stderr is closed by the caller already
            pass

    # Write out a shell-script so that we can start our proxy in a clean
    # environment:
    write_runner_shell_script(dotxpra, script)

    from xpra.log import Logger
    log = Logger("server")

    mdns_recs = []
    sockets = []
    try:
        # Initialize the TCP sockets before the display,
        # That way, errors won't make us kill the Xvfb
        # (which may not be ours to kill at that point)
        bind_tcp = parse_bind_tcp(opts.bind_tcp)
        for host, iport in bind_tcp:
            socket = setup_tcp_socket(host, iport)
            sockets.append(socket)
        if opts.mdns:
            mdns_recs.append(("tcp", bind_tcp))
    except Exception, e:
        log.error("cannot start server: failed to setup sockets: %s", e)
        return 1
コード例 #2
0
ファイル: server.py プロジェクト: svn2github/Xpra
def run_server(error_cb, opts, mode, xpra_file, extra_args):
    try:
        cwd = os.getcwd()
    except:
        cwd = os.path.expanduser("~")
        sys.stderr.write("current working directory does not exist, using '%s'\n" % cwd)
    if opts.encoding and opts.encoding=="help":
        #avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        #disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging
        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase
        sb = ServerBase()
        sb.init(opts)
        #ensures that the threaded video helper init has completed
        #(by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help
        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting  = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying  = mode == "proxy"
    clobber   = upgrading or opts.use_display

    if upgrading or shadowing:
        #there should already be one running
        opts.pulseaudio = False

    #get the display name:
    if shadowing and len(extra_args)==0:
        if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
            #just a virtual name for the only display available:
            display_name = ":0"
        else:
            from xpra.scripts.main import guess_X11_display
            display_name = guess_X11_display(opts.socket_dir)
    elif upgrading and len(extra_args)==0:
        from xpra.scripts.main import guess_xpra_display
        display_name = guess_xpra_display(opts.socket_dir)
    else:
        if len(extra_args) > 1:
            error_cb("too many extra arguments: only expected a display number")
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not proxying:
                display_name_check(display_name)
        else:
            if proxying:
                error_cb("you must specify a free virtual display name to use with the proxy server")
            if not opts.displayfd:
                error_cb("displayfd support is not enabled on this system, you must specify the display to use")
            if opts.use_display:
                #only use automatic guess for xpra displays and not X11 displays:
                from xpra.scripts.main import guess_xpra_display     #@Reimport
                display_name = guess_xpra_display(opts.socket_dir)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = 'S' + str(os.getpid())

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        error_cb("--exit-with-children specified without any children to spawn; exiting immediately")

    atexit.register(run_cleanups)
    #the server class will usually override those:
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    dotxpra = DotXpra(opts.socket_dir)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if opts.daemon:
        #daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)
        # At this point we may not know the display name,
        # so log_filename0 may point to a temporary file which we will rename later
        log_filename0 = select_log_file(dotxpra, opts.log_file, display_name)
        logfd = open_log_file(log_filename0)
        assert logfd > 2
        stdout, stderr = daemonize(logfd)
        try:
            stderr.write("Entering daemon mode; "
                 + "any further errors will be reported to:\n"
                 + ("  %s\n" % log_filename0))
        except:
            #this can happen if stderr is closed by the caller already
            pass

    if os.name=="posix":
        # Write out a shell-script so that we can start our proxy in a clean
        # environment:
        write_runner_shell_script(dotxpra, script)

    from xpra.log import Logger
    log = Logger("server")

    mdns_recs = []
    sockets = []
    try:
        # Initialize the TCP sockets before the display,
        # That way, errors won't make us kill the Xvfb
        # (which may not be ours to kill at that point)
        bind_tcp = parse_bind_tcp(opts.bind_tcp)
        for host, iport in bind_tcp:
            socket = setup_tcp_socket(host, iport)
            sockets.append(socket)
        if opts.mdns:
            mdns_recs.append(("tcp", bind_tcp))
    except Exception as e:
        log.error("cannot start server: failed to setup sockets: %s", e)
        return 1

    # Do this after writing out the shell script:
    if display_name[0] != 'S':
        os.environ["DISPLAY"] = display_name
    sanitize_env()
    configure_imsettings_env(opts.input_method)

    # Start the Xvfb server first to get the display_name if needed
    xvfb = None
    xvfb_pid = None
    if not shadowing and not proxying and not clobber:
        try:
            xvfb, display_name = start_Xvfb(opts.xvfb, display_name)
        except OSError as e:
            log.error("Error starting Xvfb: %s\n", e)
            return  1
        xvfb_pid = xvfb.pid
        #always update as we may now have the "real" display name:
        os.environ["DISPLAY"] = display_name

    if opts.daemon:
        log_filename1 = select_log_file(dotxpra, opts.log_file, display_name)
        if log_filename0 != log_filename1:
            # we now have the correct log filename, so use it:
            os.rename(log_filename0, log_filename1)
            stderr.write("Actual log file name is now: %s\n" % log_filename1)
        stdout.close()
        stderr.close()

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return  1

    #setup unix domain socket:
    socket, cleanup_socket = setup_local_socket(dotxpra, display_name, clobber, opts.mmap_group, opts.socket_permissions)
    if socket:      #win32 returns None!
        sockets.append(socket)
        if opts.mdns:
            ssh_port = get_ssh_port()
            if ssh_port:
                mdns_recs.append(("ssh", [("", ssh_port)]))

    #publish mdns records:
    if opts.mdns:
        from xpra.platform.info import get_username
        mdns_info = {"display" : display_name,
                     "username": get_username()}
        if opts.session_name:
            mdns_info["session"] = opts.session_name
        for mode, listen_on in mdns_recs:
            mdns_publish(display_name, mode, listen_on, mdns_info)

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return  1

    display = None
    if not sys.platform.startswith("win") and not sys.platform.startswith("darwin") and not proxying:
        display = verify_display_ready(xvfb, display_name, shadowing)
        if not display:
            return 1
    elif not proxying:
        assert "gtk" not in sys.modules
        import gtk          #@Reimport
        assert gtk

    if shadowing:
        from xpra.platform.shadow_server import ShadowServer
        app = ShadowServer()
        info = "shadow"
    elif proxying:
        from xpra.server.proxy_server import ProxyServer
        app = ProxyServer()
        info = "proxy"
    else:
        assert starting or upgrading
        from xpra.x11.gtk_x11 import gdk_display_source
        assert gdk_display_source
        #(now we can access the X11 server)

        if clobber:
            #get the saved pid (there should be one):
            xvfb_pid = get_xvfb_pid()
        elif xvfb_pid is not None:
            #save the new pid (we should have one):
            save_xvfb_pid(xvfb_pid)

        #check for an existing window manager:
        from xpra.x11.gtk_x11.wm import wm_check
        if not wm_check(display, opts.wm_name, upgrading):
            return 1
        try:
            # This import is delayed because the module depends on gtk:
            from xpra.x11.server import XpraServer
            from xpra.x11.bindings.window_bindings import X11WindowBindings     #@UnresolvedImport
            X11Window = X11WindowBindings()
        except ImportError as e:
            log.error("Failed to load Xpra server components, check your installation: %s" % e)
            return 1
        if not X11Window.displayHasXComposite():
            log.error("Xpra is a compositing manager, it cannot use a display which lacks the XComposite extension!")
            return 1
        app = XpraServer(clobber)
        info = "xpra"

    try:
        app.exec_cwd = cwd
        app.init(opts)
    except Exception as e:
        log.error("Error: cannot start the %s server", info, exc_info=True)
        log.error(str(e))
        log.info("")
        return 1

    #honour start child, html webserver, and setup child reaper
    if os.name=="posix" and not proxying and not upgrading and not shadowing:
        # start websockify?
        try:
            start_websockify(app.child_reaper, opts, bind_tcp)
            #websockify overrides the tcp proxy, so we must re-set it:
            app._tcp_proxy = opts.tcp_proxy
        except Exception as e:
            error_cb("failed to setup websockify html server: %s" % e)
        if opts.exit_with_children:
            assert opts.start_child, "exit-with-children was specified but start-child is missing!"
        if opts.start:
            for x in opts.start:
                if x:
                    app.start_child(x, x, True)
        if opts.start_child:
            for x in opts.start_child:
                if x:
                    app.start_child(x, x, False)

    log("%s(%s)", app.init_sockets, sockets)
    app.init_sockets(sockets)
    log("%s(%s)", app.init_when_ready, _when_ready)
    app.init_when_ready(_when_ready)

    #we got this far so the sockets have initialized and
    #the server should be able to manage the display
    #from now on, if we exit without upgrading we will also kill the Xvfb
    def kill_xvfb():
        # Close our display(s) first, so the server dying won't kill us.
        log.info("killing xvfb with pid %s" % xvfb_pid)
        import gtk  #@Reimport
        for display in gtk.gdk.display_manager_get().list_displays():
            display.close()
        os.kill(xvfb_pid, signal.SIGTERM)
    if xvfb_pid is not None and not opts.use_display and not shadowing:
        _cleanups.append(kill_xvfb)

    try:
        log("running %s", app.run)
        e = app.run()
        log("%s()=%s", app.run, e)
    except KeyboardInterrupt:
        log.info("stopping on KeyboardInterrupt")
        e = 0
    except Exception as e:
        log.error("server error", exc_info=True)
        e = -128
    if e>0:
        # Upgrading/exiting, so leave X server running
        if kill_xvfb in _cleanups:
            _cleanups.remove(kill_xvfb)
        from xpra.server.server_core import ServerCore
        if e==ServerCore.EXITING_CODE:
            log.info("exiting: not cleaning up Xvfb")
        elif cleanup_socket in _cleanups:
            log.info("upgrading: not cleaning up Xvfb or socket")
            # don't delete the new socket (not ours)
            _cleanups.remove(cleanup_socket)
        log("cleanups=%s", _cleanups)
        e = 0
    return e
コード例 #3
0
ファイル: server.py プロジェクト: svn2github/Xpra
def run_server(error_cb, opts, mode, xpra_file, extra_args):
    try:
        cwd = os.getcwd()
    except:
        cwd = os.path.expanduser("~")
        sys.stderr.write("current working directory does not exist, using '%s'\n" % cwd)
    if opts.encoding and opts.encoding == "help":
        # avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        # disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging

        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase

        sb = ServerBase()
        sb.init(opts)
        # ensures that the threaded video helper init has completed
        # (by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper

        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help

        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying = mode == "proxy"
    clobber = upgrading or opts.use_display

    # get the display name:
    if shadowing and len(extra_args) == 0:
        if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
            # just a virtual name for the only display available:
            display_name = ":0"
        else:
            from xpra.scripts.main import guess_X11_display

            display_name = guess_X11_display(opts.socket_dir)
    elif upgrading and len(extra_args) == 0:
        from xpra.scripts.main import guess_xpra_display

        display_name = guess_xpra_display(opts.socket_dir)
    else:
        if len(extra_args) > 1:
            error_cb("too many extra arguments: only expected a display number")
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not proxying:
                display_name_check(display_name)
        else:
            if proxying:
                error_cb("you must specify a free virtual display name to use with the proxy server")
            if not opts.displayfd:
                error_cb("displayfd support is not enabled on this system, you must specify the display to use")
            if opts.use_display:
                # only use automatic guess for xpra displays and not X11 displays:
                from xpra.scripts.main import guess_xpra_display  # @Reimport

                display_name = guess_xpra_display(opts.socket_dir)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = "S" + str(os.getpid())

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        error_cb("--exit-with-children specified without any children to spawn; exiting immediately")

    atexit.register(run_cleanups)
    # the server class will usually override those:
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    dotxpra = DotXpra(opts.socket_dir)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if opts.daemon:
        # daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)
        # At this point we may not know the display name,
        # so log_filename0 may point to a temporary file which we will rename later
        log_filename0 = select_log_file(dotxpra, opts.log_file, display_name)
        logfd = open_log_file(log_filename0)
        assert logfd > 2
        stdout, stderr = daemonize(logfd)
        try:
            stderr.write(
                "Entering daemon mode; " + "any further errors will be reported to:\n" + ("  %s\n" % log_filename0)
            )
        except:
            # this can happen if stderr is closed by the caller already
            pass

    # Write out a shell-script so that we can start our proxy in a clean
    # environment:
    write_runner_shell_script(dotxpra, script)

    from xpra.log import Logger

    log = Logger("server")

    mdns_recs = []
    sockets = []
    try:
        # Initialize the TCP sockets before the display,
        # That way, errors won't make us kill the Xvfb
        # (which may not be ours to kill at that point)
        bind_tcp = parse_bind_tcp(opts.bind_tcp)
        for host, iport in bind_tcp:
            socket = setup_tcp_socket(host, iport)
            sockets.append(socket)
        if opts.mdns:
            mdns_recs.append(("tcp", bind_tcp))
    except Exception, e:
        log.error("cannot start server: failed to setup sockets: %s", e)
        return 1
コード例 #4
0
ファイル: server.py プロジェクト: rudresh2319/Xpra
def run_server(error_cb, opts, mode, xpra_file, extra_args):
    try:
        cwd = os.getcwd()
    except:
        cwd = os.path.expanduser("~")
        sys.stderr.write(
            "current working directory does not exist, using '%s'\n" % cwd)
    if opts.encoding and opts.encoding == "help":
        #avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        #disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging
        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase
        sb = ServerBase()
        sb.init(opts)
        #ensures that the threaded video helper init has completed
        #(by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help
        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying = mode == "proxy"
    clobber = upgrading or opts.use_display

    if upgrading or shadowing:
        #there should already be one running
        opts.pulseaudio = False

    #get the display name:
    if shadowing and len(extra_args) == 0:
        if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
            #just a virtual name for the only display available:
            display_name = ":0"
        else:
            from xpra.scripts.main import guess_X11_display
            display_name = guess_X11_display(opts.socket_dir)
    elif upgrading and len(extra_args) == 0:
        from xpra.scripts.main import guess_xpra_display
        display_name = guess_xpra_display(opts.socket_dir)
    else:
        if len(extra_args) > 1:
            error_cb(
                "too many extra arguments: only expected a display number")
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not proxying:
                display_name_check(display_name)
        else:
            if proxying:
                error_cb(
                    "you must specify a free virtual display name to use with the proxy server"
                )
            if not opts.displayfd:
                error_cb(
                    "displayfd support is not enabled on this system, you must specify the display to use"
                )
            if opts.use_display:
                #only use automatic guess for xpra displays and not X11 displays:
                from xpra.scripts.main import guess_xpra_display  #@Reimport
                display_name = guess_xpra_display(opts.socket_dir)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = 'S' + str(os.getpid())

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        error_cb(
            "--exit-with-children specified without any children to spawn; exiting immediately"
        )

    atexit.register(run_cleanups)
    #the server class will usually override those:
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    dotxpra = DotXpra(opts.socket_dir)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if opts.daemon:
        #daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)
        # At this point we may not know the display name,
        # so log_filename0 may point to a temporary file which we will rename later
        log_filename0 = select_log_file(dotxpra, opts.log_file, display_name)
        logfd = open_log_file(log_filename0)
        assert logfd > 2
        stdout, stderr = daemonize(logfd)
        try:
            stderr.write("Entering daemon mode; " +
                         "any further errors will be reported to:\n" +
                         ("  %s\n" % log_filename0))
        except:
            #this can happen if stderr is closed by the caller already
            pass

    if os.name == "posix":
        # Write out a shell-script so that we can start our proxy in a clean
        # environment:
        write_runner_shell_script(dotxpra, script)

    from xpra.log import Logger
    log = Logger("server")

    mdns_recs = []
    sockets = []
    try:
        # Initialize the TCP sockets before the display,
        # That way, errors won't make us kill the Xvfb
        # (which may not be ours to kill at that point)
        bind_tcp = parse_bind_tcp(opts.bind_tcp)
        for host, iport in bind_tcp:
            socket = setup_tcp_socket(host, iport)
            sockets.append(socket)
        if opts.mdns:
            mdns_recs.append(("tcp", bind_tcp))
    except Exception as e:
        log.error("cannot start server: failed to setup sockets: %s", e)
        return 1

    # Do this after writing out the shell script:
    if display_name[0] != 'S':
        os.environ["DISPLAY"] = display_name
    sanitize_env()
    configure_imsettings_env(opts.input_method)

    # Start the Xvfb server first to get the display_name if needed
    xvfb = None
    xvfb_pid = None
    if not shadowing and not proxying and not clobber:
        try:
            xvfb, display_name = start_Xvfb(opts.xvfb, display_name)
        except OSError as e:
            log.error("Error starting Xvfb: %s\n", e)
            return 1
        xvfb_pid = xvfb.pid
        #always update as we may now have the "real" display name:
        os.environ["DISPLAY"] = display_name

    if opts.daemon:
        log_filename1 = select_log_file(dotxpra, opts.log_file, display_name)
        if log_filename0 != log_filename1:
            # we now have the correct log filename, so use it:
            os.rename(log_filename0, log_filename1)
            stderr.write("Actual log file name is now: %s\n" % log_filename1)
        stdout.close()
        stderr.close()

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return 1

    #setup unix domain socket:
    socket, cleanup_socket = setup_local_socket(dotxpra, display_name, clobber,
                                                opts.mmap_group,
                                                opts.socket_permissions)
    if socket:  #win32 returns None!
        sockets.append(socket)
        if opts.mdns:
            ssh_port = get_ssh_port()
            if ssh_port:
                mdns_recs.append(("ssh", [("", ssh_port)]))

    #publish mdns records:
    if opts.mdns:
        from xpra.platform.info import get_username
        mdns_info = {"display": display_name, "username": get_username()}
        if opts.session_name:
            mdns_info["session"] = opts.session_name
        for mode, listen_on in mdns_recs:
            mdns_publish(display_name, mode, listen_on, mdns_info)

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return 1

    display = None
    if not sys.platform.startswith("win") and not sys.platform.startswith(
            "darwin") and not proxying:
        display = verify_display_ready(xvfb, display_name, shadowing)
        if not display:
            return 1
    elif not proxying:
        assert "gtk" not in sys.modules
        import gtk  #@Reimport
        assert gtk

    if shadowing:
        from xpra.platform.shadow_server import ShadowServer
        app = ShadowServer()
        info = "shadow"
    elif proxying:
        from xpra.server.proxy_server import ProxyServer
        app = ProxyServer()
        info = "proxy"
    else:
        assert starting or upgrading
        from xpra.x11.gtk_x11 import gdk_display_source
        assert gdk_display_source
        #(now we can access the X11 server)

        if clobber:
            #get the saved pid (there should be one):
            xvfb_pid = get_xvfb_pid()
        elif xvfb_pid is not None:
            #save the new pid (we should have one):
            save_xvfb_pid(xvfb_pid)

        #check for an existing window manager:
        from xpra.x11.gtk_x11.wm import wm_check
        if not wm_check(display, opts.wm_name, upgrading):
            return 1
        try:
            # This import is delayed because the module depends on gtk:
            from xpra.x11.server import XpraServer
            from xpra.x11.bindings.window_bindings import X11WindowBindings  #@UnresolvedImport
            X11Window = X11WindowBindings()
        except ImportError as e:
            log.error(
                "Failed to load Xpra server components, check your installation: %s"
                % e)
            return 1
        if not X11Window.displayHasXComposite():
            log.error(
                "Xpra is a compositing manager, it cannot use a display which lacks the XComposite extension!"
            )
            return 1
        app = XpraServer(clobber)
        info = "xpra"

    try:
        app.exec_cwd = cwd
        app.init(opts)
    except Exception as e:
        log.error("Error: cannot start the %s server", info, exc_info=True)
        log.error(str(e))
        log.info("")
        return 1

    #honour start child, html webserver, and setup child reaper
    if os.name == "posix" and not proxying and not upgrading and not shadowing:
        # start websockify?
        try:
            start_websockify(app.child_reaper, opts, bind_tcp)
            #websockify overrides the tcp proxy, so we must re-set it:
            app._tcp_proxy = opts.tcp_proxy
        except Exception as e:
            error_cb("failed to setup websockify html server: %s" % e)
        if opts.exit_with_children:
            assert opts.start_child, "exit-with-children was specified but start-child is missing!"
        if opts.start:
            for x in opts.start:
                if x:
                    app.start_child(x, x, True)
        if opts.start_child:
            for x in opts.start_child:
                if x:
                    app.start_child(x, x, False)

    log("%s(%s)", app.init_sockets, sockets)
    app.init_sockets(sockets)
    log("%s(%s)", app.init_when_ready, _when_ready)
    app.init_when_ready(_when_ready)

    #we got this far so the sockets have initialized and
    #the server should be able to manage the display
    #from now on, if we exit without upgrading we will also kill the Xvfb
    def kill_xvfb():
        # Close our display(s) first, so the server dying won't kill us.
        log.info("killing xvfb with pid %s" % xvfb_pid)
        import gtk  #@Reimport
        for display in gtk.gdk.display_manager_get().list_displays():
            display.close()
        os.kill(xvfb_pid, signal.SIGTERM)

    if xvfb_pid is not None and not opts.use_display and not shadowing:
        _cleanups.append(kill_xvfb)

    try:
        log("running %s", app.run)
        e = app.run()
        log("%s()=%s", app.run, e)
    except KeyboardInterrupt:
        log.info("stopping on KeyboardInterrupt")
        e = 0
    except Exception as e:
        log.error("server error", exc_info=True)
        e = -128
    if e > 0:
        # Upgrading/exiting, so leave X server running
        if kill_xvfb in _cleanups:
            _cleanups.remove(kill_xvfb)
        from xpra.server.server_core import ServerCore
        if e == ServerCore.EXITING_CODE:
            log.info("exiting: not cleaning up Xvfb")
        elif cleanup_socket in _cleanups:
            log.info("upgrading: not cleaning up Xvfb or socket")
            # don't delete the new socket (not ours)
            _cleanups.remove(cleanup_socket)
        log("cleanups=%s", _cleanups)
        e = 0
    return e