Sfoglia il codice sorgente

Defined stopasgroup option

Roger Hoover 13 anni fa
parent
commit
3314ec302b

+ 6 - 0
CHANGES.txt

@@ -1,6 +1,12 @@
 Next release
 ------------
 
+- Add a boolean program option ``stopasgroup``, defaulting to false.
+  When true, the flag causes supervisor to send the stop signal to the
+  whole process group.  This is useful for programs, such as Flask in debug
+  mode, that do not propagate stop signals to their children, leaving them
+  orphaned.
+
 - Python 2.3 is no longer supported.  The last version that supported Python
   2.3 is Supervisor 3.0a12.
 

+ 13 - 0
docs/configuration.rst

@@ -713,6 +713,19 @@ where specified.
 
   *Introduced*: 3.0
 
+``stopasgroup``
+
+  If true, the flag causes supervisor to send the stop signal to the
+  whole process group and implies ``killasgroup``=true.  This is useful 
+  for programs, such as Flask in debug mode, that do not propagate
+  stop signals to their children, leaving them orphaned.
+
+  *Default*: false
+
+  *Required*:  No.
+
+  *Introduced*: 3.0a12
+
 ``killasgroup``
 
   If true, when resorting to send SIGKILL to the program to terminate

+ 3 - 1
supervisor/options.py

@@ -750,6 +750,7 @@ class ServerOptions(Options):
         uid = name_to_uid(get(section, 'user', None))
         stopsignal = signal_number(get(section, 'stopsignal', 'TERM'))
         stopwaitsecs = integer(get(section, 'stopwaitsecs', 10))
+        stopasgroup = boolean(get(section, 'stopasgroup', 'false'))
         killasgroup = boolean(get(section, 'killasgroup', 'false'))
         exitcodes = list_of_exitcodes(get(section, 'exitcodes', '0,2'))
         redirect_stderr = boolean(get(section, 'redirect_stderr','false'))
@@ -845,6 +846,7 @@ class ServerOptions(Options):
                 stderr_logfile_maxbytes=logfiles['stderr_logfile_maxbytes'],
                 stopsignal=stopsignal,
                 stopwaitsecs=stopwaitsecs,
+                stopasgroup=stopasgroup,
                 killasgroup=killasgroup,
                 exitcodes=exitcodes,
                 redirect_stderr=redirect_stderr,
@@ -1565,7 +1567,7 @@ class ProcessConfig(Config):
         'stderr_logfile', 'stderr_capture_maxbytes',
         'stderr_logfile_backups', 'stderr_logfile_maxbytes',
         'stderr_events_enabled',
-        'stopsignal', 'stopwaitsecs', 'killasgroup',
+        'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup',
         'exitcodes', 'redirect_stderr' ]
     optional_param_names = [ 'environment', 'serverurl' ]
 

+ 2 - 0
supervisor/skel/sample.conf

@@ -68,6 +68,7 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket
 ;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
 ;stopsignal=QUIT               ; signal used to kill process (default TERM)
 ;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
+;stopasgroup=false             ; send stop signal to the UNIX process group (default false)
 ;killasgroup=false             ; SIGKILL the UNIX process group (def false)
 ;user=chrism                   ; setuid to this UNIX account to run the program
 ;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
@@ -105,6 +106,7 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket
 ;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
 ;stopsignal=QUIT               ; signal used to kill process (default TERM)
 ;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
+;stopasgroup=false             ; send stop signal to the UNIX process group (default false)
 ;killasgroup=false             ; SIGKILL the UNIX process group (def false)
 ;user=chrism                   ; setuid to this UNIX account to run the program
 ;redirect_stderr=true          ; redirect proc stderr to stdout (default false)

+ 2 - 1
supervisor/tests/base.py

@@ -483,7 +483,7 @@ class DummyPConfig:
                  stderr_events_enabled=False,
                  stderr_logfile_backups=0, stderr_logfile_maxbytes=0,
                  redirect_stderr=False,
-                 stopsignal=None, stopwaitsecs=10, killasgroup=False,
+                 stopsignal=None, stopwaitsecs=10, stopasgroup=False, killasgroup=False,
                  exitcodes=(0,2), environment=None, serverurl=None):
         self.options = options
         self.name = name
@@ -510,6 +510,7 @@ class DummyPConfig:
             stopsignal = signal.SIGTERM
         self.stopsignal = stopsignal
         self.stopwaitsecs = stopwaitsecs
+        self.stopasgroup = stopasgroup
         self.killasgroup = killasgroup
         self.exitcodes = exitcodes
         self.environment = environment

+ 10 - 2
supervisor/tests/test_options.py

@@ -218,6 +218,7 @@ class ServerOptionsTests(unittest.TestCase):
         command=/bin/cat
         autorestart=true
         exitcodes=0,1,127
+        stopasgroup=true
         killasgroup=true
 
         [program:cat4]
@@ -276,6 +277,7 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(proc1.stdout_logfile, '/tmp/cat.log')
         self.assertEqual(proc1.stopsignal, signal.SIGKILL)
         self.assertEqual(proc1.stopwaitsecs, 5)
+        self.assertEqual(proc1.stopasgroup, False)
         self.assertEqual(proc1.killasgroup, False)
         self.assertEqual(proc1.stdout_logfile_maxbytes,
                          datatypes.byte_size('50MB'))
@@ -299,6 +301,7 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(proc2.uid, None)
         self.assertEqual(proc2.stdout_logfile, '/tmp/cat2.log')
         self.assertEqual(proc2.stopsignal, signal.SIGTERM)
+        self.assertEqual(proc2.stopasgroup, False)
         self.assertEqual(proc2.killasgroup, False)
         self.assertEqual(proc2.stdout_logfile_maxbytes, 1024)
         self.assertEqual(proc2.stdout_logfile_backups, 2)
@@ -323,6 +326,7 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(proc3.stdout_logfile_backups, 10)
         self.assertEqual(proc3.exitcodes, [0,1,127])
         self.assertEqual(proc3.stopsignal, signal.SIGTERM)
+        self.assertEqual(proc3.stopasgroup, True)
         self.assertEqual(proc3.killasgroup, True)
 
         cat4 = options.process_group_configs[3]
@@ -344,6 +348,7 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(proc4_a.stdout_logfile_backups, 10)
         self.assertEqual(proc4_a.exitcodes, [0,2])
         self.assertEqual(proc4_a.stopsignal, signal.SIGTERM)
+        self.assertEqual(proc4_a.stopasgroup, False)
         self.assertEqual(proc4_a.killasgroup, False)
 
         proc4_b = cat4.process_configs[1]
@@ -360,6 +365,7 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(proc4_b.stdout_logfile_backups, 10)
         self.assertEqual(proc4_b.exitcodes, [0,2])
         self.assertEqual(proc4_b.stopsignal, signal.SIGTERM)
+        self.assertEqual(proc4_b.stopasgroup, False)
         self.assertEqual(proc4_b.killasgroup, False)
 
         here = os.path.abspath(os.getcwd())
@@ -628,6 +634,7 @@ class ServerOptionsTests(unittest.TestCase):
         stdout_events_enabled = true
         stopsignal = KILL
         stopwaitsecs = 100
+        stopasgroup = true
         killasgroup = true
         exitcodes = 1,4
         redirect_stderr = false
@@ -653,6 +660,7 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(pconfig.stdout_logfile_maxbytes, 104857600)
         self.assertEqual(pconfig.stdout_events_enabled, True)
         self.assertEqual(pconfig.stopsignal, signal.SIGKILL)
+        self.assertEqual(pconfig.stopasgroup, True)
         self.assertEqual(pconfig.killasgroup, True)
         self.assertEqual(pconfig.stopwaitsecs, 100)
         self.assertEqual(pconfig.exitcodes, [1,4])
@@ -1341,7 +1349,7 @@ class TestProcessConfig(unittest.TestCase):
                      'stderr_logfile', 'stderr_capture_maxbytes',
                      'stderr_events_enabled',
                      'stderr_logfile_backups', 'stderr_logfile_maxbytes',
-                     'stopsignal', 'stopwaitsecs', 'killasgroup', 'exitcodes',
+                     'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup', 'exitcodes',
                      'redirect_stderr', 'environment'):
             defaults[name] = name
         defaults.update(kw)
@@ -1415,7 +1423,7 @@ class FastCGIProcessConfigTest(unittest.TestCase):
                      'stderr_logfile', 'stderr_capture_maxbytes',
                      'stderr_events_enabled',
                      'stderr_logfile_backups', 'stderr_logfile_maxbytes',
-                     'stopsignal', 'stopwaitsecs', 'killasgroup', 'exitcodes',
+                     'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup', 'exitcodes',
                      'redirect_stderr', 'environment'):
             defaults[name] = name
         defaults.update(kw)

+ 1 - 0
supervisor/tests/test_supervisord.py

@@ -259,6 +259,7 @@ class SupervisordTests(unittest.TestCase):
                 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0,
                 'redirect_stderr': False,
                 'stopsignal': None, 'stopwaitsecs': 10,
+                'stopasgroup': False,
                 'killasgroup': False,
                 'exitcodes': (0,2), 'environment': None, 'serverurl': None }
             result.update(params)