[Piuparts-commits] [SCM] piuparts git repository branch, master, updated. eda668423fa87898c59d1075118693714aa5a053

Holger Levsen holger at layer-acht.org
Fri Dec 23 10:26:20 UTC 2011


The following commit has been merged in the master branch:
commit 4ad3f94c2ace7e56ecfdf1938d827986a71bb26f
Author: Andreas Beckmann <debian at abeckmann.de>
Date:   Mon Nov 21 01:46:01 2011 +0100

    stop using Popen.communicate()
    
    from http://docs.python.org/library/subprocess.html:
        Popen.communicate(input=None)
        ...
            Note: The data read is buffered in memory, so do not use
                  this method if the data size is large or unlimited.
    
    Bad maintainer scripts can go havoc, especially with
    DEBIAN_FRONTEND=noninteractive and stdin=/dev/null.
    
    Limit each command to 2 MB of output and terminate/kill it
    afterwards.
    
    Signed-off-by: Andreas Beckmann <debian at abeckmann.de>

diff --git a/piuparts.py b/piuparts.py
index 7924c1e..db96c53 100644
--- a/piuparts.py
+++ b/piuparts.py
@@ -384,7 +384,26 @@ def run(command, ignore_errors=False):
     devnull = open('/dev/null', 'r')
     p = subprocess.Popen(command, env=env, stdin=devnull, 
                          stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-    (output, _) = p.communicate()
+    output = ""
+    excessive_output = False
+    while p.poll() is None:
+        """Read 64 KB chunks, but depending on the output buffering behavior
+        of the command we may get less even if more output is coming later.
+        Abort after reading 2 MB."""
+        output += p.stdout.read(1 << 16)
+        if (len(output) > (1 << 21)):
+            excessive_output = True
+            logging.error("Terminating command due to excessive output")
+            p.terminate()
+            for i in range(10):
+                time.sleep(0.5)
+                if p.poll() is not None:
+                    break
+            else:
+                logging.error("Killing command due to excessive output")
+                p.kill()
+            p.wait()
+            break
     devnull.close()
 
     if output:
@@ -398,6 +417,8 @@ def run(command, ignore_errors=False):
     else:
         logging.error("Command failed (status=%d): %s\n%s" % 
               (p.returncode, repr(command), indent_string(output)))
+        if excessive_output:
+            logging.error("Command was terminated while producing excessive output")
         panic()
     return p.returncode, output
 

-- 
piuparts git repository



More information about the Piuparts-commits mailing list