add --daemon option to serve command. for issue 45.
authorVadim Gelfer <vadim.gelfer@gmail.com>
Fri, 17 Feb 2006 16:29:30 -0800
changeset 1740 f95654385065
parent 1736 50de0887bbcd
child 1741 9777298fed84
add --daemon option to serve command. for issue 45. code looks odd because it is portable to windows. windows does not have os.fork, so have to spawn and use pipe to tell parent ready instead.
doc/hg.1.txt
mercurial/commands.py
--- a/doc/hg.1.txt	Fri Feb 17 08:26:21 2006 -0800
+++ b/doc/hg.1.txt	Fri Feb 17 16:29:30 2006 -0800
@@ -543,10 +543,12 @@
 
     options:
     -A, --accesslog <file>   name of access log file to write to
+    -d, --daemon             run server in background, as a daemon
     -E, --errorlog <file>    name of error log file to write to
     -a, --address <addr>     address to use
     -p, --port <n>           port to use (default: 8000)
     -n, --name <name>        name to show in web pages (default: working dir)
+    --pid-file <file>        write server process ID to given file
     -t, --templatedir <path> web templates to use
     -6, --ipv6               use IPv6 in addition to IPv4
 
--- a/mercurial/commands.py	Fri Feb 17 08:26:21 2006 -0800
+++ b/mercurial/commands.py	Fri Feb 17 16:29:30 2006 -0800
@@ -2022,6 +2022,16 @@
         if opts[o]:
             ui.setconfig("web", o, opts[o])
 
+    if opts['daemon'] and not opts['daemon_pipefd']:
+        rfd, wfd = os.pipe()
+        args = sys.argv[:]
+        args.append('--daemon-pipefd=' + str(wfd))
+        pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
+                         args[0], args)
+        os.close(wfd)
+        os.read(rfd, 1)
+        os._exit(0)
+
     try:
         httpd = hgweb.create_server(repo)
     except socket.error, inst:
@@ -2040,6 +2050,24 @@
             ui.status(_('listening at http://%s:%d/\n') % (addr, port))
         else:
             ui.status(_('listening at http://%s/\n') % addr)
+
+    if opts['pid_file']:
+        fp = open(opts['pid_file'], 'w')
+        fp.write(str(os.getpid()))
+        fp.close()
+
+    if opts['daemon_pipefd']:
+        wfd = int(opts['daemon_pipefd'])
+        os.write(wfd, 'y')
+        os.close(wfd)
+        sys.stdout.flush()
+        sys.stderr.flush()
+        fd = os.open(util.nulldev, os.O_RDWR)
+        if fd != 0: os.dup2(fd, 0)
+        if fd != 1: os.dup2(fd, 1)
+        if fd != 2: os.dup2(fd, 2)
+        if fd not in (0, 1, 2): os.close(fd)
+
     httpd.serve_forever()
 
 def status(ui, repo, *pats, **opts):
@@ -2476,11 +2504,14 @@
     "^serve":
         (serve,
          [('A', 'accesslog', '', _('name of access log file to write to')),
+          ('d', 'daemon', None, _('run server in background')),
+          ('', 'daemon-pipefd', '', ''),
           ('E', 'errorlog', '', _('name of error log file to write to')),
           ('p', 'port', 0, _('port to use (default: 8000)')),
           ('a', 'address', '', _('address to use')),
           ('n', 'name', '',
            _('name to show in web pages (default: working dir)')),
+          ('', 'pid-file', '', _('name of file to write process ID to')),
           ('', 'stdio', None, _('for remote clients')),
           ('t', 'templates', '', _('web templates to use')),
           ('', 'style', '', _('template style to use')),