[Zodb-checkins] SVN: zdaemon/trunk/ Added a separate option, stop-timout, to control how long to wait

jim cvs-admin at zope.org
Mon Jun 4 14:17:15 UTC 2012


Log message for revision 126562:
  Added a separate option, stop-timout, to control how long to wait
  for a graceful shutdown.
  
  Previously, this was controlled by backoff-limit, which didn't make
  much sense.
  

Changed:
  U   zdaemon/trunk/CHANGES.txt
  U   zdaemon/trunk/src/zdaemon/README.txt
  U   zdaemon/trunk/src/zdaemon/component.xml
  U   zdaemon/trunk/src/zdaemon/tests/tests.py
  U   zdaemon/trunk/src/zdaemon/zdoptions.py
  U   zdaemon/trunk/src/zdaemon/zdrun.py

-=-
Modified: zdaemon/trunk/CHANGES.txt
===================================================================
--- zdaemon/trunk/CHANGES.txt	2012-06-04 13:06:20 UTC (rev 126561)
+++ zdaemon/trunk/CHANGES.txt	2012-06-04 14:17:09 UTC (rev 126562)
@@ -2,13 +2,16 @@
  Changelog
 ===========
 
-
-2.0.5 (unreleased)
+3.0.0 (unreleased)
 ==================
 
-- Nothing changed yet.
+- Added a separate option, stop-timout, to control how long to wait
+  for a graceful shutdown.
 
+  Previously, this was controlled by backoff-limit, which didn't make
+  much sense.
 
+
 2.0.4 (2009-04-20)
 ==================
 

Modified: zdaemon/trunk/src/zdaemon/README.txt
===================================================================
--- zdaemon/trunk/src/zdaemon/README.txt	2012-06-04 13:06:20 UTC (rev 126561)
+++ zdaemon/trunk/src/zdaemon/README.txt	2012-06-04 14:17:09 UTC (rev 126562)
@@ -398,6 +398,16 @@
         status code in this list makes zdaemon give up.  To disable
         this, change the value to an empty list.
 
+stop-timeout
+        Command-line option: -T or --stop-timeout SECONDS
+
+        This defaults to 500 seconds (5 minutes).
+
+        When a stop command is issued, a SIGTERM signal is sent to the
+        process.  zdaemon waits for stop-timeout seconds for the
+        process to gracefully exit. If the process doesn't exit in
+        that time, a SIGKILL signal is sent.
+
 user
         Command-line option: -u or --user.
 

Modified: zdaemon/trunk/src/zdaemon/component.xml
===================================================================
--- zdaemon/trunk/src/zdaemon/component.xml	2012-06-04 13:06:20 UTC (rev 126561)
+++ zdaemon/trunk/src/zdaemon/component.xml	2012-06-04 14:17:09 UTC (rev 126562)
@@ -185,6 +185,17 @@
       </description>
     </key>
 
+    <key name="stop-timeout" datatype="integer" required="no" default="300">
+      <description>
+        When a stop command is issued, a SIGTERM signal is sent to the
+        process.  zdaemon waits for stop-timeout seconds for the
+        process to gracefully exit. If the process doesn't exit in
+        that time, a SIGKILL signal is sent.
+
+        This defaults to 500 seconds (5 minutes).
+      </description>
+    </key>
+
     <key name="user" datatype="string"
          required="no">
       <description>

Modified: zdaemon/trunk/src/zdaemon/tests/tests.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/tests.py	2012-06-04 13:06:20 UTC (rev 126561)
+++ zdaemon/trunk/src/zdaemon/tests/tests.py	2012-06-04 14:17:09 UTC (rev 126562)
@@ -38,13 +38,16 @@
     zdaemon_loc = os.path.dirname(os.path.dirname(zdaemon.__file__))
     zconfig_loc = os.path.dirname(os.path.dirname(ZConfig.__file__))
 
+def write(name, text):
+    with open(name, 'w') as f:
+        f.write(text)
 
 def make_sure_non_daemon_mode_doesnt_hang_when_program_exits():
     """
     The whole awhile bit that waits for a program to start
     whouldn't be used on non-daemon mode.
 
-    >>> open('conf', 'w').write(
+    >>> write('conf',
     ... '''
     ... <runner>
     ...   program sleep 1
@@ -60,7 +63,7 @@
     """
     If a program doesn't start, we don't want to wait for ever.
 
-    >>> open('conf', 'w').write(
+    >>> write('conf',
     ... '''
     ... <runner>
     ...   program sleep
@@ -82,7 +85,7 @@
 configuration arguments.  To deal with this, we'll allow duplicate
 arguments that have the same values.
 
-    >>> open('conf', 'w').write(
+    >>> write('conf',
     ... '''
     ... <runner>
     ...   program sleep 10
@@ -99,6 +102,45 @@
 
 """
 
+def test_stop_timeout():
+    r"""
+
+    >>> write('t.py',
+    ... '''
+    ... import time, signal
+    ... signal.signal(signal.SIGTERM, lambda *a: None)
+    ... while 1: time.sleep(9)
+    ... ''')
+
+    >>> write('conf',
+    ... '''
+    ... <runner>
+    ...   program %s t.py
+    ...   stop-timeout 1
+    ... </runner>
+    ... ''' % sys.executable)
+
+    >>> system("./zdaemon -Cconf start")
+    . .
+    daemon process started, pid=21446
+
+    >>> import threading, time
+    >>> thread = threading.Thread(
+    ...     target=system, args=("./zdaemon -Cconf stop",),
+    ...     kwargs=dict(quiet=True))
+    >>> thread.start()
+    >>> time.sleep(.2)
+
+    >>> system("./zdaemon -Cconf status")
+    program running; pid=15372
+
+    >>> thread.join(2)
+
+    >>> system("./zdaemon -Cconf status")
+    daemon manager not running
+
+    """
+
 def setUp(test):
     test.globs['_td'] = td = []
     here = os.getcwd()
@@ -123,7 +165,7 @@
     for f in test.globs['_td']:
         f()
 
-def system(command, input=''):
+def system(command, input='', quiet=False):
     p = subprocess.Popen(
         command, shell=True,
         stdin=subprocess.PIPE,
@@ -132,7 +174,9 @@
     if input:
         p.stdin.write(input)
     p.stdin.close()
-    print p.stdout.read(),
+    data = p.stdout.read()
+    if not quiet:
+        print data,
     p.wait()
 
 def checkenv(match):

Modified: zdaemon/trunk/src/zdaemon/zdoptions.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdoptions.py	2012-06-04 13:06:20 UTC (rev 126561)
+++ zdaemon/trunk/src/zdaemon/zdoptions.py	2012-06-04 14:17:09 UTC (rev 126562)
@@ -364,13 +364,16 @@
     -h/--help -- print usage message and exit
     -b/--backoff-limit SECONDS -- set backoff limit to SECONDS (default 10)
     -d/--daemon -- run as a proper daemon; fork a subprocess, close files etc.
-    -f/--forever -- run forever (by default, exit when backoff limit is exceeded)
+    -f/--forever -- run forever (by default, exit when backoff limit
+                    is exceeded)
     -h/--help -- print this usage message and exit
     -s/--socket-name SOCKET -- Unix socket name for client (default "zdsock")
+    -T/--stop-timeout SECONDS -- How long to wait for a graceful exit.
     -u/--user USER -- run as this user (or numeric uid)
     -m/--umask UMASK -- use this umask for daemon subprocess (default is 022)
     -x/--exit-codes LIST -- list of fatal exit codes (default "0,2")
-    -z/--directory DIRECTORY -- directory to chdir to when using -d (default off)
+    -z/--directory DIRECTORY -- directory to chdir to when using -d
+                                (default off)
     action [arguments] -- see below
 
     Actions are commands like "start", "stop" and "status".  If -i is
@@ -386,6 +389,8 @@
         ZDOptions.__init__(self)
         self.add("backofflimit", "runner.backoff_limit",
                  "b:", "backoff-limit=", int, default=10)
+        self.add("stoptimeut", "runner.stop_timeout",
+                 "T:", "stop-timeout=", int, default=300)
         self.add("daemon", "runner.daemon", "d", "daemon", flag=1, default=1)
         self.add("forever", "runner.forever", "f", "forever",
                  flag=1, default=0)

Modified: zdaemon/trunk/src/zdaemon/zdrun.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdrun.py	2012-06-04 13:06:20 UTC (rev 126561)
+++ zdaemon/trunk/src/zdaemon/zdrun.py	2012-06-04 14:17:09 UTC (rev 126562)
@@ -538,7 +538,7 @@
             self.proc.kill(signal.SIGTERM)
             self.sendreply("Sent SIGTERM")
             self.killing = 1
-            self.delay = time.time() + self.options.backofflimit
+            self.delay = time.time() + self.options.stoptimeut
         else:
             self.sendreply("Application already stopped")
 
@@ -551,7 +551,7 @@
             self.proc.kill(signal.SIGTERM)
             self.sendreply("Sent SIGTERM; will restart later")
             self.killing = 1
-            self.delay = time.time() + self.options.backofflimit
+            self.delay = time.time() + self.options.stoptimeut
         else:
             self.proc.spawn()
             self.sendreply("Application started")



More information about the Zodb-checkins mailing list