ia64/xen-unstable

changeset 10998:ae14b5b77938

[XEND] Daemonise vncviewer when it is spawned from xend.

There are various reasons it should be daemonized, but the particular
problem we hit was that YaST called "xm create" and waited on output on
stdout/stderr; xm then spawned vncviewer (which never closed its
inherited stdout and stderr); xm then would exit, but YaST still had
open file descriptors, and therefore waited forever. It would be
possible to work around in YaST, but it seemed cleaner to daemonize
vncviewer.

Signed-off-by: Charles Coffing <ccoffing@novell.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Aug 08 10:21:51 2006 +0100 (2006-08-08)
parents 9e061d0dc394
children 986cf8354d11
files tools/python/xen/xm/create.py
line diff
     1.1 --- a/tools/python/xen/xm/create.py	Tue Aug 08 10:17:42 2006 +0100
     1.2 +++ b/tools/python/xen/xm/create.py	Tue Aug 08 10:21:51 2006 +0100
     1.3 @@ -844,14 +844,58 @@ def choose_vnc_display():
     1.4  
     1.5  vncpid = None
     1.6  
     1.7 +def daemonize(prog, args):
     1.8 +    """Runs a program as a daemon with the list of arguments.  Returns the PID
     1.9 +    of the daemonized program, or returns 0 on error.
    1.10 +    """
    1.11 +    r, w = os.pipe()
    1.12 +    pid = os.fork()
    1.13 +
    1.14 +    if pid == 0:
    1.15 +        os.close(r)
    1.16 +        w = os.fdopen(w, 'w')
    1.17 +        os.setsid()
    1.18 +        try:
    1.19 +            pid2 = os.fork()
    1.20 +        except:
    1.21 +            pid2 = None
    1.22 +        if pid2 == 0:
    1.23 +            os.chdir("/")
    1.24 +            for fd in range(0, 256):
    1.25 +                try:
    1.26 +                    os.close(fd)
    1.27 +                except:
    1.28 +                    pass
    1.29 +            os.open("/dev/null", os.O_RDWR)
    1.30 +            os.dup2(0, 1)
    1.31 +            os.dup2(0, 2)
    1.32 +            os.execvp(prog, args)
    1.33 +            os._exit(1)
    1.34 +        else:
    1.35 +            w.write(str(pid2 or 0))
    1.36 +            w.close()
    1.37 +            os._exit(0)
    1.38 +
    1.39 +    os.close(w)
    1.40 +    r = os.fdopen(r)
    1.41 +    daemon_pid = int(r.read())
    1.42 +    r.close()
    1.43 +    os.waitpid(pid, 0)
    1.44 +    return daemon_pid
    1.45 +
    1.46  def spawn_vnc(display):
    1.47 +    """Spawns a vncviewer that listens on the specified display.  On success,
    1.48 +    returns the port that the vncviewer is listening on and sets the global
    1.49 +    vncpid.  On failure, returns 0.  Note that vncviewer is daemonized.
    1.50 +    """
    1.51      vncargs = (["vncviewer", "-log", "*:stdout:0",
    1.52              "-listen", "%d" % (VNC_BASE_PORT + display) ])
    1.53 -    global vncpid    
    1.54 -    vncpid = os.spawnvp(os.P_NOWAIT, "vncviewer", vncargs)
    1.55 +    global vncpid
    1.56 +    vncpid = daemonize("vncviewer", vncargs)
    1.57 +    if vncpid == 0:
    1.58 +        return 0
    1.59 +    return VNC_BASE_PORT + display
    1.60  
    1.61 -    return VNC_BASE_PORT + display
    1.62 -    
    1.63  def preprocess_vnc(vals):
    1.64      """If vnc was specified, spawn a vncviewer in listen mode
    1.65      and pass its address to the domain on the kernel command line.