Parcourir la source

Test handle_procs_with_delay.

Chris McDonough il y a 19 ans
Parent
commit
381a6afde3
2 fichiers modifiés avec 69 ajouts et 28 suppressions
  1. 22 19
      src/supervisor/supervisord.py
  2. 47 9
      src/supervisor/tests.py

+ 22 - 19
src/supervisor/supervisord.py

@@ -314,10 +314,11 @@ class Subprocess:
                 os._exit(127)
 
     def stop(self):
+        """ Administrative stop """
         self.administrative_stop = 1
+        self.reportstatusmsg = None
         # backoff needs to come before kill on MacOS, as there's
         # an apparent a race condition if it comes after
-        self.reportstatusmsg = None
         self.do_backoff()
         return self.kill(self.config.stopsignal)
 
@@ -516,12 +517,6 @@ class Supervisor:
                 if case:
                     p.spawn()
             
-    def handle_procs_with_waitstatus(self):
-        processes = self.processes.values()
-        for proc in processes:
-            if proc.waitstatus:
-                proc.reportstatus()
-
     def stop_all(self):
         processes = self.processes.values()
         processes.sort()
@@ -531,22 +526,29 @@ class Supervisor:
             if proc.pid:
                 proc.stop()
 
+    def handle_procs_with_waitstatus(self):
+        processes = self.processes.values()
+        for proc in processes:
+            if proc.waitstatus:
+                proc.reportstatus()
+
     def handle_procs_with_delay(self):
         delayprocs = []
         now = time.time()
         timeout = self.options.backofflimit
-        for name in self.processes.keys():
-            proc = self.processes[name]
-            if proc.delay:
-                delayprocs.append(proc)
-                timeout = max(0, min(timeout, proc.delay - now))
-                if timeout <= 0:
-                    proc.delay = 0
-                    if proc.killing and proc.pid:
-                        self.options.logger.info(
-                            'killing %r (%s) with SIGKILL' % (name, proc.pid))
-                        proc.do_backoff()
-                        proc.kill(signal.SIGKILL)
+        processes = self.processes.values()
+        delayprocs = [ proc for proc in processes if proc.delay ]
+        for proc in delayprocs:
+            time_left = proc.delay - now
+            time_left = max(0, min(timeout, time_left))
+            if time_left <= 0:
+                proc.delay = 0
+                if proc.killing and proc.pid:
+                    self.options.logger.info(
+                        'killing %r (%s) with SIGKILL' % (proc.config.name,
+                                                          proc.pid))
+                    proc.do_backoff()
+                    proc.kill(signal.SIGKILL)
         return delayprocs
 
     def reap(self):
@@ -627,6 +629,7 @@ class Supervisor:
                 if not self.stopping:
                     self.stop_all()
                     self.stopping = True
+
                 # reget the delay list after attempting to stop
                 delayprocs = self.handle_procs_with_delay()
                 if not delayprocs:

+ 47 - 9
src/supervisor/tests.py

@@ -1301,7 +1301,22 @@ class SupervisordTests(unittest.TestCase):
         self.assertEqual(process3.spawned, True)
         self.assertEqual(process4.spawned, False)
 
-    def handle_procs_with_waitstatus(self):
+    def test_stop_all(self):
+        options = DummyOptions()
+        pconfig1 = DummyPConfig('process1', 'process1', '/bin/process1')
+        process1 = DummyProcess(options, pconfig1)
+        pconfig2 = DummyPConfig('process2', 'process2', '/bin/process2')
+        process2 = DummyProcess(options, pconfig2)
+        process2.pid = 1
+        supervisord = self._makeOne(options)
+        supervisord.processes = {'killed': process1, 'error': process2}
+
+        supervisord.stop_all()
+        self.assertEqual(process1.stop_called, False)
+        self.assertEqual(process2.stop_called, True)
+        
+        
+    def test_handle_procs_with_waitstatus(self):
         options = DummyOptions()
         pconfig1 = DummyPConfig('process1', 'process1', '/bin/process1')
         process1 = DummyProcess(options, pconfig1)
@@ -1315,21 +1330,23 @@ class SupervisordTests(unittest.TestCase):
         self.assertEqual(process1.status_reported, False)
         self.assertEqual(process2.status_reported, True)
 
-    def test_stop_all(self):
+    def test_handle_procs_with_delay(self):
         options = DummyOptions()
         pconfig1 = DummyPConfig('process1', 'process1', '/bin/process1')
         process1 = DummyProcess(options, pconfig1)
+        process1.delay = time.time()
+        process1.killing = True
+        process1.pid = 1
         pconfig2 = DummyPConfig('process2', 'process2', '/bin/process2')
         process2 = DummyProcess(options, pconfig2)
-        process2.pid = 1
         supervisord = self._makeOne(options)
         supervisord.processes = {'killed': process1, 'error': process2}
 
-        supervisord.stop_all()
-        self.assertEqual(process1.stop_called, False)
-        self.assertEqual(process2.stop_called, True)
-        
+        supervisord.handle_procs_with_delay()
+        self.assertEqual(process1.killed_with, signal.SIGKILL)
+        self.assertEqual(process2.killed_with, None)
         
+
 class ControllerTests(unittest.TestCase):
     def _getTargetClass(self):
         from supervisorctl import Controller
@@ -1741,6 +1758,8 @@ class DummyProcess:
         self.spawned = False
         self.state = state
         self.error_at_clear = False
+        self.status_reported = False
+        self.killed_with = None
 
     def removelogs(self):
         if self.error_at_clear:
@@ -1755,6 +1774,9 @@ class DummyProcess:
         self.killing = False
         self.pid = 0
 
+    def kill(self, signal):
+        self.killed_with = signal
+
     def do_backoff(self):
         self.backoff_done = True
 
@@ -1805,8 +1827,6 @@ class DummyLogger:
 class DummyOptions:
 
     TRACE = 5
-    directory = None
-    waitpid_return = None, None
 
     def __init__(self):
         self.identifier = 'supervisor'
@@ -1822,6 +1842,21 @@ class DummyOptions:
         self.socket_map = {}
         self.mood = 1
         self.mustreopen = False
+        self.realizeargs = None
+        self.fds_cleaned_up = False
+        self.rlimit_set = False
+        self.setuid_called = False
+        self.httpserver_opened = False
+        self.signals_set = False
+        self.daemonized = False
+        self.make_logger_messages = None
+        self.autochildlogs_created = False
+        self.autochildlogdir_cleared = False
+        self.cleaned_up = False
+        self.pidfile_written = False
+        self.directory = None
+        self.waitpid_return = None, None
+        self.kills = {}
 
     def getLogger(self, *args):
         logger = DummyLogger()
@@ -1876,6 +1911,9 @@ class DummyOptions:
     def make_process(self, config):
         return DummyProcess(self, config)
 
+    def kill(self, pid, sig):
+        self.kills[pid] = sig
+
 class DummyClientOptions:
     def __init__(self):
         self.prompt = 'supervisor'