Ver Fonte

Fix a crash if IOError occurs while making dispatchers. Closes #87

Mike Naberezny há 10 anos atrás
pai
commit
862fea1dd2
3 ficheiros alterados com 34 adições e 1 exclusões
  1. 5 0
      CHANGES.txt
  2. 1 1
      supervisor/process.py
  3. 28 0
      supervisor/tests/test_process.py

+ 5 - 0
CHANGES.txt

@@ -43,6 +43,11 @@
   disallowed because any messages written to ``stderr`` would interfere
   with the eventlistener protocol on ``stdout``.
 
+- Fixed a bug where spawning a process could cause ``supervisord`` to crash
+  if an ``IOError`` occurred while setting up logging.  One way this could
+  happen is if a log filename was accidentally set to a directory instead
+  of a file.  Thanks to Grzegorz Nosek for reporting this issue.
+
 3.1.3 (2014-10-28)
 ------------------
 

+ 1 - 1
supervisor/process.py

@@ -221,7 +221,7 @@ class Subprocess(object):
 
         try:
             self.dispatchers, self.pipes = self.config.make_dispatchers(self)
-        except OSError as why:
+        except (OSError, IOError) as why:
             code = why.args[0]
             if code == errno.EMFILE:
                 # too many file descriptors open

+ 28 - 0
supervisor/tests/test_process.py

@@ -260,6 +260,34 @@ class SubprocessTests(unittest.TestCase):
         self.assertEqual(event1.__class__, events.ProcessStateStartingEvent)
         self.assertEqual(event2.__class__, events.ProcessStateBackoffEvent)
 
+    def test_spawn_fail_make_dispatchers_eisdir(self):
+        options = DummyOptions()
+        config = DummyPConfig(options, name='cat', command='/bin/cat',
+                              stdout_logfile='/a/directory') # not a file
+        def raise_eisdir(envelope):
+            raise IOError(errno.EISDIR)
+        config.make_dispatchers = raise_eisdir
+        instance = self._makeOne(config)
+        from supervisor.states import ProcessStates
+        instance.state = ProcessStates.BACKOFF
+        from supervisor import events
+        L = []
+        events.subscribe(events.ProcessStateEvent, lambda x: L.append(x))
+        result = instance.spawn()
+        self.assertEqual(result, None)
+        self.assertEqual(instance.spawnerr,
+                         "unknown error making dispatchers: EISDIR")
+        self.assertEqual(options.logger.data[0],
+                         "spawnerr: unknown error making dispatchers: EISDIR")
+        self.assertTrue(instance.delay)
+        self.assertTrue(instance.backoff)
+        from supervisor.states import ProcessStates
+        self.assertEqual(instance.state, ProcessStates.BACKOFF)
+        self.assertEqual(len(L), 2)
+        event1, event2 = L
+        self.assertEqual(event1.__class__, events.ProcessStateStartingEvent)
+        self.assertEqual(event2.__class__, events.ProcessStateBackoffEvent)
+
     def test_spawn_fork_fail_eagain(self):
         options = DummyOptions()
         options.fork_error = errno.EAGAIN