python: use communicate to fix Popen deadlock
authorJoe Guo <joeg@catalyst.net.nz>
Fri, 15 Sep 2017 04:13:26 +0000 (16:13 +1200)
committerKarolin Seeger <kseeger@samba.org>
Fri, 17 Nov 2017 11:04:37 +0000 (12:04 +0100)
`Popen.wait()` will deadlock when using stdout=PIPE and/or stderr=PIPE and the
child process generates large output to a pipe such that it blocks waiting for
the OS pipe buffer to accept more data. Use communicate() to avoid that.

Signed-off-by: Joe Guo <joeg@catalyst.net.nz>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Thu Oct 19 09:27:16 CEST 2017 on sn-devel-144

(cherry picked from commit 5dc773a5b00834c7a53130a73a48f49048bd55e8)

Autobuild-User(v4-5-test): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(v4-5-test): Tue Nov 14 14:35:22 CET 2017 on sn-devel-144

python/samba/tests/__init__.py

index a629fa5942367ee825019d9fd9348e2856a23117..6960c0ca3ae7e41d4c3527500b94f71e0e0e907b 100644 (file)
@@ -798,20 +798,22 @@ class BlackboxTestCase(TestCaseInTempDir):
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE,
                              shell=True)
-        retcode = p.wait()
+        stdoutdata, stderrdata = p.communicate()
+        retcode = p.returncode
         if retcode != expected:
             raise BlackboxProcessError(retcode,
                                        line,
-                                       p.stdout.read(),
-                                       p.stderr.read())
+                                       stdoutdata,
+                                       stderrdata)
 
     def check_output(self, line):
         line = self._make_cmdline(line)
         p = subprocess.Popen(line, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, close_fds=True)
-        retcode = p.wait()
+        stdoutdata, stderrdata = p.communicate()
+        retcode = p.returncode
         if retcode:
-            raise BlackboxProcessError(retcode, line, p.stdout.read(), p.stderr.read())
-        return p.stdout.read()
+            raise BlackboxProcessError(retcode, line, stdoutdata, stderrdata)
+        return stdoutdata
 
 
 def connect_samdb(samdb_url, lp=None, session_info=None, credentials=None,