Procházet zdrojové kódy

Fold 'start_necessary' into 'transition'. I don't know why they were
separate before.

Chris McDonough před 18 roky
rodič
revize
e09bd0f828

+ 47 - 68
src/supervisor/process.py

@@ -23,6 +23,7 @@ import traceback
 import signal
 
 from supervisor.states import ProcessStates
+from supervisor.states import SupervisorStates
 from supervisor.states import getProcessStateDescription
 from supervisor.states import STOPPED_STATES
 
@@ -292,7 +293,7 @@ class Subprocess:
         self.administrative_stop = 1
         return self.kill(self.config.stopsignal)
 
-    def fatal(self):
+    def give_up(self):
         self.delay = 0
         self.backoff = 0
         self.system_stop = 1
@@ -445,35 +446,64 @@ class Subprocess:
 
     def transition(self):
         now = time.time()
+        state = self.state
 
-        state = self.get_state()
-
-        # we need to transition processes between BACKOFF ->
-        # FATAL and STARTING -> RUNNING within here
         logger = self.config.options.logger
 
-        if state == ProcessStates.BACKOFF:
-            if self.backoff > self.config.startretries:
-                # BACKOFF -> FATAL if the proc has exceeded its number
-                # of retries
-                self.fatal()
-                msg = ('entered FATAL state, too many start retries too '
-                       'quickly')
-                logger.info('gave up: %s %s' % (self.config.name, msg))
+        if self.config.options.mood > SupervisorStates.RESTARTING:
+            # dont start any processes if supervisor is shutting down
+            if state == ProcessStates.EXITED:
+                if self.config.autorestart:
+                    if self.config.autorestart is RestartUnconditionally:
+                        # EXITED -> STARTING
+                        self.spawn()
+                    else: # autorestart is RestartWhenExitUnexpected
+                        if self.exitstatus not in self.config.exitcodes:
+                            # EXITED -> STARTING
+                            self.spawn()
+            elif state == ProcessStates.STOPPED and not self.laststart:
+                if self.config.autostart:
+                    # STOPPED -> STARTING
+                    self.spawn()
+            elif state == ProcessStates.BACKOFF:
+                if self.backoff <= self.config.startretries:
+                    if now > self.delay:
+                        # BACKOFF -> STARTING
+                        self.spawn()
 
-        elif state == ProcessStates.STARTING:
+        if state == ProcessStates.STARTING:
             if now - self.laststart > self.config.startsecs:
                 # STARTING -> RUNNING if the proc has started
                 # successfully and it has stayed up for at least
                 # proc.config.startsecs,
                 self.delay = 0
                 self.backoff = 0
+                self._assertInState(ProcessStates.STARTING)
+                self.change_state(ProcessStates.RUNNING)
                 msg = (
                     'entered RUNNING state, process has stayed up for '
                     '> than %s seconds (startsecs)' % self.config.startsecs)
                 logger.info('success: %s %s' % (self.config.name, msg))
-                self._assertInState(ProcessStates.STARTING)
-                self.change_state(ProcessStates.RUNNING)
+
+        if state == ProcessStates.BACKOFF:
+            if self.backoff > self.config.startretries:
+                # BACKOFF -> FATAL if the proc has exceeded its number
+                # of retries
+                self.give_up()
+                msg = ('entered FATAL state, too many start retries too '
+                       'quickly')
+                logger.info('gave up: %s %s' % (self.config.name, msg))
+
+        elif state == ProcessStates.STOPPING:
+            time_left = self.delay - now
+            if time_left <= 0:
+                # kill processes which are taking too long to stop with a final
+                # sigkill.  if this doesn't kill it, the process will be stuck
+                # in the STOPPING state forever.
+                self.config.options.logger.warn(
+                    'killing %r (%s) with SIGKILL' % (self.config.name,
+                                                      self.pid))
+                self.kill(signal.SIGKILL)
 
 class ProcessGroupBase:
     def __init__(self, config):
@@ -498,31 +528,6 @@ class ProcessGroupBase:
         for process in self.processes.values():
             process.reopenlogs()
 
-    def start_necessary(self):
-        processes = self.processes.values()
-        processes.sort() # asc by priority
-        now = time.time()
-
-        for p in processes:
-            state = p.get_state()
-            if state == ProcessStates.STOPPED and not p.laststart:
-                if p.config.autostart:
-                    # STOPPED -> STARTING
-                    p.spawn()
-            elif state == ProcessStates.EXITED:
-                if p.config.autorestart:
-                    if p.config.autorestart is RestartUnconditionally:
-                        # EXITED -> STARTING
-                        p.spawn()
-                    else: # autorestart is RestartWhenExitUnexpected
-                        if p.exitstatus not in p.config.exitcodes:
-                            # EXITED -> STARTING
-                            p.spawn()
-            elif state == ProcessStates.BACKOFF:
-                if now > p.delay:
-                    # BACKOFF -> STARTING
-                    p.spawn()
-
     def stop_all(self):
         processes = self.processes.values()
         processes.sort()
@@ -538,7 +543,7 @@ class ProcessGroupBase:
                 proc.stop()
             elif state == ProcessStates.BACKOFF:
                 # BACKOFF -> FATAL
-                proc.fatal()
+                proc.give_up()
 
     def get_delay_processes(self):
         """ Processes which are starting or stopping """
@@ -549,30 +554,6 @@ class ProcessGroupBase:
         return [ x for x in self.processes.values() if x.get_state() not in
                  STOPPED_STATES ]
 
-    def get_undead(self):
-        """ Processes which we've attempted to stop but which haven't responded
-        to a kill request within a given amount of time (stopwaitsecs) """
-        now = time.time()
-        processes = self.processes.values()
-        undead = []
-
-        for proc in processes:
-            if proc.get_state() == ProcessStates.STOPPING:
-                time_left = proc.delay - now
-                if time_left <= 0:
-                    undead.append(proc)
-        return undead
-
-    def kill_undead(self):
-        for undead in self.get_undead():
-            # kill processes which are taking too long to stop with a final
-            # sigkill.  if this doesn't kill it, the process will be stuck
-            # in the STOPPING state forever.
-            self.config.options.logger.warn(
-                'killing %r (%s) with SIGKILL' % (undead.config.name,
-                                                  undead.pid))
-            undead.kill(signal.SIGKILL)
-
     def get_dispatchers(self):
         dispatchers = {}
         for process in self.processes.values():
@@ -581,7 +562,6 @@ class ProcessGroupBase:
 
 class ProcessGroup(ProcessGroupBase):
     def transition(self):
-        self.kill_undead()
         for proc in self.processes.values():
             proc.transition()
 
@@ -602,7 +582,6 @@ class EventListenerPool(ProcessGroupBase):
             self._bufferEvent(event.event)
 
     def transition(self):
-        self.kill_undead()
         for proc in self.processes.values():
             proc.transition()
         if self.event_buffer:

+ 1 - 4
src/supervisor/supervisord.py

@@ -172,10 +172,7 @@ class Supervisor:
             pgroups = self.process_groups.values()
             pgroups.sort()
 
-            if self.options.mood > SupervisorStates.RESTARTING:
-                [ group.start_necessary() for group in pgroups ]
-
-            elif self.options.mood < SupervisorStates.RUNNING:
+            if self.options.mood < SupervisorStates.RUNNING:
                 if not self.stopping:
                     # first time, set the stopping flag, do a
                     # notification and set stop_groups

+ 1 - 5
src/supervisor/tests/base.py

@@ -367,7 +367,7 @@ class DummyProcess:
     def finish(self, pid, sts):
         self.finished = pid, sts
 
-    def fatal(self):
+    def give_up(self):
         from supervisor.process import ProcessStates
         self.state = ProcessStates.FATAL
 
@@ -746,16 +746,12 @@ class DummyPGroupConfig:
 class DummyProcessGroup:
     def __init__(self, config):
         self.config = config
-        self.necessary_started = False
         self.transitioned = False
         self.all_stopped = False
         self.delay_processes = []
         self.dispatchers = {}
         self.unstopped_processes = []
 
-    def start_necessary(self):
-        self.necessary_started = True
-
     def transition(self):
         self.transitioned = True
 

+ 258 - 144
src/supervisor/tests/test_process.py

@@ -25,7 +25,7 @@ class SubprocessTests(unittest.TestCase):
         clear()
 
     def test_getProcessStateDescription(self):
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         from supervisor.process import getProcessStateDescription
         for statename, code in ProcessStates.__dict__.items():
             self.assertEqual(getProcessStateDescription(code), statename)
@@ -536,7 +536,7 @@ class SubprocessTests(unittest.TestCase):
         self.assertEqual(options.kills[11], signal.SIGTERM)
         self.assertEqual(dispatcher.write_event_handled, True)
 
-    def test_fatal(self):
+    def test_give_up(self):
         options = DummyOptions()
         config = DummyPConfig(options, 'test', '/test')
         instance = self._makeOne(config)
@@ -545,7 +545,7 @@ class SubprocessTests(unittest.TestCase):
         from supervisor import events
         events.subscribe(events.FatalFromBackoffEvent, lambda x: L.append(x))
         instance.state = ProcessStates.BACKOFF
-        instance.fatal()
+        instance.give_up()
         self.assertEqual(instance.system_stop, 1)
         self.assertFalse(instance.delay)
         self.assertFalse(instance.backoff)
@@ -591,7 +591,7 @@ class SubprocessTests(unittest.TestCase):
         from supervisor.states import ProcessStates
         from supervisor import events
         events.subscribe(events.StoppingFromStartingEvent,lambda x: L.append(x))
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         instance.state = ProcessStates.STARTING
         instance.kill(signal.SIGTERM)
         self.assertEqual(options.logger.data[0], 'killing test (pid 11) with '
@@ -609,7 +609,7 @@ class SubprocessTests(unittest.TestCase):
         from supervisor.states import ProcessStates
         from supervisor import events
         events.subscribe(events.StoppingFromRunningEvent, lambda x: L.append(x))
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         instance.state = ProcessStates.RUNNING
         instance.kill(signal.SIGTERM)
         self.assertEqual(options.logger.data[0], 'killing test (pid 11) with '
@@ -627,7 +627,7 @@ class SubprocessTests(unittest.TestCase):
         from supervisor.states import ProcessStates
         from supervisor import events
         events.subscribe(events.Event,lambda x: L.append(x))
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         instance.state = ProcessStates.STOPPING
         instance.kill(signal.SIGKILL)
         self.assertEqual(options.logger.data[0], 'killing test (pid 11) with '
@@ -771,60 +771,265 @@ class SubprocessTests(unittest.TestCase):
 
         self.assertEqual(L, [instance, instance1, instance2])
 
-    def test_transition(self):
+    def test_transition_stopped_to_starting_supervisor_stopping(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
         options = DummyOptions()
+        options.mood = SupervisorStates.SHUTDOWN
 
-        from supervisor.process import ProcessStates
+        # this should not be spawned, as supervisor is shutting down
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.laststart = 0
+        process.state = ProcessStates.STOPPED
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.STOPPED)
+        self.assertEqual(L, [])
 
-        # this should go from BACKOFF to FATAL via transition()
-        pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
-        process1 = self._makeOne(pconfig1)
-        process1.laststart = 1
-        process1.backoff = 10000
-        process1.delay = 1
-        process1.system_stop = 0
-        process1.stdout_buffer = 'abc'
-        process1.stderr_buffer = 'def'
-        process1.state = ProcessStates.BACKOFF
+    def test_transition_stopped_to_starting_supervisor_running(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+        options.mood = SupervisorStates.RUNNING
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.laststart = 0
+        process.state = ProcessStates.STOPPED
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.STARTING)
+        self.assertEqual(L[0].__class__, events.StartingFromStoppedEvent)
+
+    def test_transition_exited_to_starting_supervisor_stopping(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+        options.mood = SupervisorStates.SHUTDOWN
+
+        # this should not be spawned, as supervisor is shutting down
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        from supervisor.datatypes import RestartUnconditionally
+        pconfig.autorestart = RestartUnconditionally
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.system_stop = 1
+        process.state = ProcessStates.EXITED
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.EXITED)
+        self.assertEqual(process.system_stop, 1)
+        self.assertEqual(L, [])
+
+    def test_transition_exited_to_starting_uncond_supervisor_running(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        from supervisor.datatypes import RestartUnconditionally
+        pconfig.autorestart = RestartUnconditionally
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.state = ProcessStates.EXITED
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.STARTING)
+        self.assertEqual(L[0].__class__, events.StartingFromExitedEvent)
+
+    def test_transition_exited_to_starting_condit_supervisor_running(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        from supervisor.datatypes import RestartWhenExitUnexpected
+        pconfig.autorestart = RestartWhenExitUnexpected
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.state = ProcessStates.EXITED
+        process.exitstatus = 'bogus'
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.STARTING)
+        self.assertEqual(L[0].__class__, events.StartingFromExitedEvent)
+
+    def test_transition_exited_to_starting_condit_fls_supervisor_running(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        from supervisor.datatypes import RestartWhenExitUnexpected
+        pconfig.autorestart = RestartWhenExitUnexpected
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.state = ProcessStates.EXITED
+        process.exitstatus = 0
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.EXITED)
+        self.assertEqual(L, [])
+
+    def test_transition_backoff_to_starting_supervisor_stopping(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+        options.mood = SupervisorStates.SHUTDOWN
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.delay = 0
+        process.backoff = 0
+        process.state = ProcessStates.BACKOFF
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.BACKOFF)
+        self.assertEqual(L, [])
+
+    def test_transition_backoff_to_starting_supervisor_running(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+        options.mood = SupervisorStates.RUNNING
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.delay = 0
+        process.backoff = 0
+        process.state = ProcessStates.BACKOFF
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.STARTING)
+        self.assertEqual(L[0].__class__, events.StartingFromBackoffEvent)
+
+    def test_transition_backoff_to_starting_supervisor_running_notyet(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates, SupervisorStates
+        options = DummyOptions()
+        options.mood = SupervisorStates.RUNNING
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.delay = sys.maxint
+        process.backoff = 0
+        process.state = ProcessStates.BACKOFF
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.BACKOFF)
+        self.assertEqual(L, [])
+
+    def test_transition_starting_to_running(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates
+
+        options = DummyOptions()
+
+        # this should go from STARTING to RUNNING via transition()
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.backoff = 1
+        process.delay = 1
+        process.system_stop = 0
+        process.laststart = 1
+        process.pid = 1
+        process.stdout_buffer = 'abc'
+        process.stderr_buffer = 'def'
+        process.state = ProcessStates.STARTING
+        process.transition()
 
+        # this implies RUNNING
+        self.assertEqual(process.backoff, 0)
+        self.assertEqual(process.delay, 0)
+        self.assertEqual(process.system_stop, 0)
+        self.assertEqual(options.logger.data[0],
+                         'success: process entered RUNNING state, process has '
+                         'stayed up for > than 10 seconds (startsecs)')
+        self.assertEqual(L[0].__class__, events.RunningFromStartingEvent)
+
+    def test_transition_backoff_to_fatal(self):
         from supervisor import events
         L = []
         events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates
+        options = DummyOptions()
 
-        process1.transition()
+        # this should go from BACKOFF to FATAL via transition()
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.laststart = 1
+        process.backoff = 10000
+        process.delay = 1
+        process.system_stop = 0
+        process.stdout_buffer = 'abc'
+        process.stderr_buffer = 'def'
+        process.state = ProcessStates.BACKOFF
+
+        process.transition()
 
         # this implies FATAL
-        self.assertEqual(process1.backoff, 0)
-        self.assertEqual(process1.delay, 0)
-        self.assertEqual(process1.system_stop, 1)
+        self.assertEqual(process.backoff, 0)
+        self.assertEqual(process.delay, 0)
+        self.assertEqual(process.system_stop, 1)
         self.assertEqual(options.logger.data[0],
-                         'gave up: process1 entered FATAL state, too many start'
+                         'gave up: process entered FATAL state, too many start'
                          ' retries too quickly')
         self.assertEqual(L[0].__class__, events.FatalFromBackoffEvent)
 
+    def test_transition_stops_unkillable_notyet(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates
+        options = DummyOptions()
 
-        # this should go from STARTING to RUNNING via transition()
-        pconfig2 = DummyPConfig(options, 'process2', 'process2','/bin/process2')
-        process2 = self._makeOne(pconfig2)
-        process2.backoff = 1
-        process2.delay = 1
-        process2.system_stop = 0
-        process2.laststart = 1
-        process2.pid = 1
-        process2.stdout_buffer = 'abc'
-        process2.stderr_buffer = 'def'
-        process2.state = ProcessStates.STARTING
-
-        process2.transition()
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.delay = sys.maxint
+        process.state = ProcessStates.STOPPING
 
-        # this implies RUNNING
-        self.assertEqual(process2.backoff, 0)
-        self.assertEqual(process2.delay, 0)
-        self.assertEqual(process2.system_stop, 0)
-        self.assertEqual(options.logger.data[1],
-                         'success: process2 entered RUNNING state, process has '
-                         'stayed up for > than 10 seconds (startsecs)')
-        self.assertEqual(L[1].__class__, events.RunningFromStartingEvent)
+        process.transition()
+        self.assertEqual(process.state, ProcessStates.STOPPING)
+        self.assertEqual(L, [])
+
+    def test_transition_stops_unkillable(self):
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateChangeEvent, lambda x: L.append(x))
+        from supervisor.states import ProcessStates
+        options = DummyOptions()
+
+        pconfig = DummyPConfig(options, 'process', 'process','/bin/process')
+        process = self._makeOne(pconfig)
+        process.delay = 0
+        process.pid = 1
+        process.killing = 0
+        process.state = ProcessStates.STOPPING
+
+        process.transition()
+        self.assertEqual(process.killing, 1)
+        self.assertNotEqual(process.delay, 0)
+        self.assertEqual(process.state, ProcessStates.STOPPING)
+        self.assertEqual(options.logger.data[0],
+                         "killing 'process' (1) with SIGKILL")
+        import signal
+        self.assertEqual(options.kills[1], signal.SIGKILL)
+        self.assertEqual(L, [])
 
     def test_change_state_doesnt_notify_if_no_state_change(self):
         options = DummyOptions()
@@ -843,7 +1048,7 @@ class ProcessGroupBaseTests(unittest.TestCase):
 
     def test_get_delay_processes(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
         process1.delay = 1
@@ -853,99 +1058,8 @@ class ProcessGroupBaseTests(unittest.TestCase):
         delayed = group.get_delay_processes()
         self.assertEqual(delayed, [process1])
         
-    def test_get_undead(self):
-        options = DummyOptions()
-        from supervisor.process import ProcessStates
-
-        pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
-        process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
-        process1.delay = time.time() - 1
-
-        pconfig2 = DummyPConfig(options, 'process2', 'process2','/bin/process2')
-        process2 = DummyProcess(pconfig2, state=ProcessStates.STOPPING)
-        process2.delay = time.time() + 1000
-
-        pconfig3 = DummyPConfig(options, 'process3', 'process3','/bin/process3')
-        process3 = DummyProcess(pconfig3, state=ProcessStates.RUNNING)
-
-        gconfig = DummyPGroupConfig(options,
-                                    pconfigs=[pconfig1, pconfig2, pconfig3])
-        group = self._makeOne(gconfig)
-        group.processes = { 'process1': process1, 'process2': process2,
-                            'process3':process3 }
-
-        undead = group.get_undead()
-        self.assertEqual(undead, [process1])
-
-    def test_kill_undead(self):
-        options = DummyOptions()
-        from supervisor.process import ProcessStates
-
-        pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
-        process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
-        process1.delay = time.time() - 1
-
-        pconfig2 = DummyPConfig(options, 'process2', 'process2','/bin/process2')
-        process2 = DummyProcess(pconfig2, state=ProcessStates.STOPPING)
-        process2.delay = time.time() + 1000
-
-        gconfig = DummyPGroupConfig(
-            options,
-            pconfigs=[pconfig1, pconfig2])
-        group = self._makeOne(gconfig)
-        group.processes = { 'process1': process1, 'process2': process2}
-
-        group.kill_undead()
-        self.assertEqual(process1.killed_with, signal.SIGKILL)
-
-    def test_start_necessary(self):
-        from supervisor.process import ProcessStates
-        from supervisor import datatypes
-        options = DummyOptions()
-        pconfig1 = DummyPConfig(options, 'killed', 'killed', '/bin/killed',
-                                autorestart=datatypes.RestartUnconditionally)
-        process1 = DummyProcess(pconfig1, ProcessStates.EXITED)
-        pconfig2 = DummyPConfig(options, 'error', 'error', '/bin/error')
-        process2 = DummyProcess(pconfig2, ProcessStates.FATAL)
-
-        pconfig3 = DummyPConfig(options, 'notstarted', 'notstarted',
-                                '/bin/notstarted', autostart=True)
-        process3 = DummyProcess(pconfig3, ProcessStates.STOPPED)
-        pconfig4 = DummyPConfig(options, 'wontstart', 'wonstart',
-                                '/bin/wontstart', autostart=True)
-        process4 = DummyProcess(pconfig4, ProcessStates.BACKOFF)
-        pconfig5 = DummyPConfig(options, 'backingoff', 'backingoff',
-                                '/bin/backingoff', autostart=True)
-        process5 = DummyProcess(pconfig5, ProcessStates.BACKOFF)
-
-        now = time.time()
-        process5.delay = now + 1000
-
-        pconfig6 = DummyPConfig(options,
-                                'shouldntrestart', 'shouldntrestart',
-                                '/bin/shouldntrestart',
-                                autorestart=datatypes.RestartWhenExitUnexpected,
-                                exitcodes=[1])
-        process6 = DummyProcess(pconfig6, ProcessStates.EXITED)
-        process6.exitstatus = 1
-
-        gconfig = DummyPGroupConfig(
-            options,
-            pconfigs=[pconfig1, pconfig2, pconfig3, pconfig4, pconfig5])
-        group = self._makeOne(gconfig)
-        group.processes = {'killed': process1, 'error': process2,
-                           'notstarted':process3, 'wontstart':process4,
-                           'backingoff':process5, 'shouldntrestart':process6}
-        group.start_necessary()
-        self.assertEqual(process1.spawned, True)
-        self.assertEqual(process2.spawned, False)
-        self.assertEqual(process3.spawned, True)
-        self.assertEqual(process4.spawned, True)
-        self.assertEqual(process5.spawned, False)
-        self.assertEqual(process6.spawned, False)
-
     def test_stop_all(self):
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         options = DummyOptions()
 
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
@@ -976,7 +1090,7 @@ class ProcessGroupBaseTests(unittest.TestCase):
 
     def test_get_dispatchers(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
         process1.dispatchers = {4:None}
@@ -991,7 +1105,7 @@ class ProcessGroupBaseTests(unittest.TestCase):
         
     def test_reopenlogs(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
         gconfig = DummyPGroupConfig(options, pconfigs=[pconfig1])
@@ -1002,7 +1116,7 @@ class ProcessGroupBaseTests(unittest.TestCase):
 
     def test_removelogs(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
         gconfig = DummyPGroupConfig(options, pconfigs=[pconfig1])
@@ -1043,7 +1157,7 @@ class ProcessGroupTests(ProcessGroupBaseTests):
 
     def test_transition(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.STOPPING)
         gconfig = DummyPGroupConfig(options, pconfigs=[pconfig1])
@@ -1218,7 +1332,7 @@ class EventListenerPoolTests(ProcessGroupBaseTests):
 
     def test_transition_nobody_listenening(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.STARTING)
         gconfig = DummyPGroupConfig(options, pconfigs=[pconfig1])
@@ -1239,7 +1353,7 @@ class EventListenerPoolTests(ProcessGroupBaseTests):
     
     def test_transition_event_proc_not_running(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.STARTING)
         gconfig = DummyPGroupConfig(options, pconfigs=[pconfig1])
@@ -1262,7 +1376,7 @@ class EventListenerPoolTests(ProcessGroupBaseTests):
 
     def test_transition_event_proc_running(self):
         options = DummyOptions()
-        from supervisor.process import ProcessStates
+        from supervisor.states import ProcessStates
         pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
         process1 = DummyProcess(pconfig1, state=ProcessStates.RUNNING)
         gconfig = DummyPGroupConfig(options, pconfigs=[pconfig1])

+ 0 - 1
src/supervisor/tests/test_supervisord.py

@@ -176,7 +176,6 @@ class SupervisordTests(unittest.TestCase):
         supervisord.process_groups = {'foo': pgroup}
         options.select_result = [6], [7, 8], []
         supervisord.runforever(test=True)
-        self.assertEqual(pgroup.necessary_started, True)
         self.assertEqual(pgroup.transitioned, True)
         self.assertEqual(readable.read_event_handled, True)
         self.assertEqual(writable.write_event_handled, True)