瀏覽代碼

More testability enhancements.

Chris McDonough 19 年之前
父節點
當前提交
c26ddcde66
共有 2 個文件被更改,包括 44 次插入36 次删除
  1. 41 36
      src/supervisor/supervisord.py
  2. 3 0
      src/supervisor/tests.py

+ 41 - 36
src/supervisor/supervisord.py

@@ -133,18 +133,38 @@ class Subprocess:
             for handler in self.childlog.handlers:
                 handler.reopen()
 
+    def log(self, data):
+        if data:
+            if self.childlog:
+                self.childlog.info(data)
+            msg = '%s output:\n%s' % (self.config.name, data)
+            self.options.logger.log(self.options.TRACE, msg)
+
+    def log_writebuffer(self):
+        if self.writebuffer:
+            self.log(self.writebuffer)
+            self.writebuffer = ''
+
     def drain(self):
-        stdout = _readfd(self.stdoutfd)
-        stderr = _readfd(self.stderrfd)
-        self.writebuffer = stdout
+        self.drain_stdout()
+        self.drain_stderr()
+
+    def drain_stderr(self, *ignored):
+        output = _readfd(self.stderrfd)
         if self.config.log_stderr:
-            self.writebuffer += stderr
+            self.writebuffer += output
 
-    def readable_fds(self):
-        if self.stdoutfd and self.stderrfd:
-            return self.stdoutfd, self.stderrfd
-        return []
- 
+    def drain_stdout(self, *ignored):
+        output = _readfd(self.stdoutfd)
+        self.writebuffer += output
+
+    def fd_drains(self):
+        if not self.stdoutfd or not self.stderrfd:
+            return []
+
+        return ( [ self.stderrfd, self.drain_stderr],
+                 [self.stdoutfd, self.drain_stdout] )
+        
     def get_execv_args(self):
         """Internal: turn a program name into a file name, using $PATH,
         make sure it exists """
@@ -436,22 +456,6 @@ class Subprocess:
         # sort by priority
         return cmp(self.config.priority, other.config.priority)
 
-    def log(self, data):
-        if data:
-            if self.childlog:
-                self.childlog.info(data)
-
-    def log_output(self, data):
-        if data:
-            self.log(data)
-            msg = '%s output:\n%s' % (self.config.name, data)
-            self.options.logger.log(self.options.TRACE, msg)
-
-    def log_writebuffer(self):
-        if self.writebuffer:
-            self.log_output(self.writebuffer)
-            self.writebuffer = ''
-
     def get_state(self):
         if self.killing:
             return ProcessStates.STOPPING
@@ -538,11 +542,11 @@ class Supervisor:
 
             # process output fds
             for proc in self.processes.values():
-                readable_fds = proc.readable_fds()
-                for fd in readable_fds:
-                    r.append(fd)
-                    process_map[fd] = proc
                 proc.log_writebuffer()
+                drains = proc.fd_drains()
+                for fd, drain in drains:
+                    r.append(fd)
+                    process_map[fd] = drain
 
             # medusa i/o fds
             for fd, dispatcher in socket_map.items():
@@ -556,10 +560,10 @@ class Supervisor:
                     self.stop_all()
                     self.stopping = True
 
-                # if there are no delayed processes, it's OK to stop or reload
-                delayprocs = self.handle_procs_with_delay()
-                if not delayprocs:
-                    break # reload or stop
+                # if there are no delayed processes (we're done killing
+                # everything), it's OK to stop or reload
+                if not self.handle_procs_with_delay():
+                    break
 
             try:
                 r, w, x = select.select(r, w, x, timeout)
@@ -575,8 +579,9 @@ class Supervisor:
 
             for fd in r:
                 if process_map.has_key(fd):
-                    proc = process_map[fd]
-                    proc.drain()
+                    drain = process_map[fd]
+                    # drain the file descriptor
+                    drain(fd)
 
                 if socket_map.has_key(fd):
                     try:
@@ -599,7 +604,7 @@ class Supervisor:
             self.reap()
 
             if self.options.signal:
-                # clear and handle a signal
+                # clear and handle the last signal
                 sig, self.options.signal = self.options.signal, None
                 if sig in (signal.SIGTERM, signal.SIGINT, signal.SIGQUIT):
                     self.options.logger.critical(

+ 3 - 0
src/supervisor/tests.py

@@ -1806,6 +1806,9 @@ class DummyProcess:
     def drain(self):
         self.drained = True
 
+    def fd_drains(self):
+        return []
+
     def reportstatus(self):
         self.status_reported = True