You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gs...@apache.org on 2012/03/07 02:17:07 UTC

svn commit: r1297822 - /subversion/trunk/tools/server-side/svnpubsub/svnwcsub.py

Author: gstein
Date: Wed Mar  7 01:17:06 2012
New Revision: 1297822

URL: http://svn.apache.org/viewvc?rev=1297822&view=rev
Log:
Add the ability to run as a daemon (specified by the --daemon command
line option).

* tools/server-side/svnpubsub/svnwcsub.py:
  (class Daemon): new subclass of daemonize.Daemon to run the server,
    once it has become a daemon
  (handle_options): don't write out a pidfile if we're going to run as
    a daemon. gotta wait until after the double-fork.
  (main): add a new --daemon option. require a logfile and pidfile
    when running as a daemon. start up the daemon as appropriate.

Modified:
    subversion/trunk/tools/server-side/svnpubsub/svnwcsub.py

Modified: subversion/trunk/tools/server-side/svnpubsub/svnwcsub.py
URL: http://svn.apache.org/viewvc/subversion/trunk/tools/server-side/svnpubsub/svnwcsub.py?rev=1297822&r1=1297821&r2=1297822&view=diff
==============================================================================
--- subversion/trunk/tools/server-side/svnpubsub/svnwcsub.py (original)
+++ subversion/trunk/tools/server-side/svnpubsub/svnwcsub.py Wed Mar  7 01:17:06 2012
@@ -46,6 +46,7 @@ from twisted.web.client import HTTPClien
 from urlparse import urlparse
 from xml.sax import handler, make_parser
 
+import daemonize
 
 # check_output() is only available in Python 2.7. Allow us to run with
 # earlier versions
@@ -392,6 +393,22 @@ class ReloadableConfig(ConfigParser.Safe
         return str(option)
 
 
+class Daemon(daemonize.Daemon):
+    def __init__(self, logfile, pidfile, bdec):
+        daemonize.Daemon.__init__(self, logfile, pidfile)
+
+        self.bdec = bdec
+
+    def setup(self):
+        # There is no setup which the parent needs to wait for.
+        pass
+
+    def run(self):
+        # Start the BDEC (on the main thread), then start up twisted
+        self.bdec.start()
+        reactor.run()
+
+
 def prepare_logging(logfile):
     "Log to the specified file, or to stdout if None."
 
@@ -420,7 +437,9 @@ def handle_options(options):
     # Set up the logging, then process the rest of the options.
     prepare_logging(options.logfile)
 
-    if options.pidfile:
+    # In daemon mode, we let the daemonize module handle the pidfile.
+    # Otherwise, we should write this (foreground) PID into the file.
+    if options.pidfile and not options.daemon:
         pid = os.getpid()
         open(options.pidfile, 'w').write('%s\n' % pid)
         logging.info('pid %d written to %s', pid, options.pidfile)
@@ -465,6 +484,8 @@ def main(args):
                       help='switch to this GID before running')
     parser.add_option('--umask',
                       help='set this (octal) umask before running')
+    parser.add_option('--daemon', action='store_true',
+                      help='run as a background daemon')
 
     options, extra = parser.parse_args(args)
 
@@ -472,15 +493,26 @@ def main(args):
         parser.error('CONFIG_FILE is required')
     config_file = extra[0]
 
+    if options.daemon and not options.logfile:
+        parser.error('LOGFILE is required when running as a daemon')
+    if options.daemon and not options.pidfile:
+        parser.error('PIDFILE is required when running as a daemon')
+
     # Process any provided options.
     handle_options(options)
 
     c = ReloadableConfig(config_file)
     bdec = BigDoEverythingClasss(c)
 
-    # Start the BDEC on the main thread, then start up twisted
-    bdec.start()
-    reactor.run()
+    # We manage the logfile ourselves (along with possible rotation). The
+    # daemon process can just drop stdout/stderr into /dev/null.
+    d = Daemon('/dev/null', options.pidfile, bdec)
+    if options.daemon:
+        # Daemonize the process and call sys.exit() with appropriate code
+        d.daemonize_exit()
+    else:
+        # Just run in the foreground (the default)
+        d.foreground()
 
 
 if __name__ == "__main__":