Przeglądaj źródła

Disallow redirect_stderr=true for eventlisteners. Closes #220

Mike Naberezny 10 lat temu
rodzic
commit
4420af41f3
3 zmienionych plików z 38 dodań i 2 usunięć
  1. 4 0
      CHANGES.txt
  2. 14 2
      supervisor/options.py
  3. 20 0
      supervisor/tests/test_options.py

+ 4 - 0
CHANGES.txt

@@ -39,6 +39,10 @@
 - Errors caused by bad values in a config file now show the config section
   to make debugging easier.  Patch by Marc Abramowitz.
 
+- Setting ``redirect_stderr=true`` in an `[eventlistener:x]`` section is now
+  disallowed because any messages written to ``stderr`` would interfere
+  with the eventlistener protocol on ``stdout``.
+
 3.1.3 (2014-10-28)
 ------------------
 

+ 14 - 2
supervisor/options.py

@@ -665,7 +665,6 @@ class ServerOptions(Options):
             kwargs['expansions'] = expansions
             return parser.saneget(section, opt, default, **kwargs)
 
-
         # process heterogeneous groups
         for section in all_sections:
             if not section.startswith('group:'):
@@ -710,6 +709,7 @@ class ServerOptions(Options):
             # and stopped last at mainloop exit
             priority = integer(get(section, 'priority', -1))
             buffer_size = integer(get(section, 'buffer_size', 10))
+
             result_handler = get(section, 'result_handler',
                                        'supervisor.dispatchers:default_handler')
             try:
@@ -717,12 +717,14 @@ class ServerOptions(Options):
             except ImportError:
                 raise ValueError('%s cannot be resolved within [%s]' % (
                     result_handler, section))
+
             pool_event_names = [x.upper() for x in
                                 list_of_strings(get(section, 'events', ''))]
             pool_event_names = set(pool_event_names)
             if not pool_event_names:
                 raise ValueError('[%s] section requires an "events" line' %
                                  section)
+
             from supervisor.events import EventTypes
             pool_events = []
             for pool_event_name in pool_event_names:
@@ -731,6 +733,13 @@ class ServerOptions(Options):
                     raise ValueError('Unknown event type %s in [%s] events' %
                                      (pool_event_name, section))
                 pool_events.append(pool_event)
+
+            redirect_stderr = boolean(get(section, 'redirect_stderr', 'false'))
+            if redirect_stderr:
+                raise ValueError('[%s] section sets redirect_stderr=true '
+                    'but this is not allowed because it will interfere '
+                    'with the eventlistener protocol' % section)
+
             processes=self.processes_from_section(parser, section, pool_name,
                                                   EventListenerConfig)
 
@@ -861,6 +870,7 @@ class ServerOptions(Options):
         stopasgroup = boolean(get(section, 'stopasgroup', 'false'))
         killasgroup = boolean(get(section, 'killasgroup', stopasgroup))
         exitcodes = list_of_exitcodes(get(section, 'exitcodes', '0,2'))
+        # see also redirect_stderr check in process_groups_from_parser()
         redirect_stderr = boolean(get(section, 'redirect_stderr','false'))
         numprocs = integer(get(section, 'numprocs', 1))
         numprocs_start = integer(get(section, 'numprocs_start', 0))
@@ -1785,7 +1795,9 @@ class ProcessConfig(Config):
 
 class EventListenerConfig(ProcessConfig):
     def make_dispatchers(self, proc):
-        use_stderr = not self.redirect_stderr
+        # always use_stderr=True for eventlisteners because mixing stderr
+        # messages into stdout would break the eventlistener protocol
+        use_stderr = True
         p = self.options.make_pipes(use_stderr)
         stdout_fd,stderr_fd,stdin_fd = p['stdout'],p['stderr'],p['stdin']
         dispatchers = {}

+ 20 - 0
supervisor/tests/test_options.py

@@ -1498,6 +1498,26 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(dog1.command, '/bin/dog')
         self.assertEqual(dog1.priority, 1)
 
+    def test_event_listener_pool_disallows_redirect_stderr(self):
+        text = lstrip("""\
+        [eventlistener:dog]
+        events=PROCESS_COMMUNICATION
+        command = /bin/dog
+        redirect_stderr = True
+        """)
+        from supervisor.options import UnhosedConfigParser
+        from supervisor.tests.base import dummy_handler
+        config = UnhosedConfigParser()
+        config.read_string(text)
+        instance = self._makeOne()
+        try:
+            instance.process_groups_from_parser(config)
+            self.fail('nothing raised')
+        except ValueError as exc:
+            self.assertEqual(exc.args[0], '[eventlistener:dog] section sets '
+                'redirect_stderr=true but this is not allowed because it '
+                'will interfere with the eventlistener protocol')
+
     def test_event_listener_pool_with_event_results_handler(self):
         text = lstrip("""\
         [eventlistener:dog]