From: Daniel Dunbar Date: Tue, 22 Sep 2009 09:50:38 +0000 (+0000) Subject: lit: When executing shell scripts internally, don't allow piped stderr on any X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5a461dd513dddaec6fd30196cb8f8680659a6e0d;p=oota-llvm.git lit: When executing shell scripts internally, don't allow piped stderr on any commands except the last one, instead redirect the stderr to a temporary file. This sidesteps a potential deadlocking issue. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82538 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/utils/lit/TestRunner.py b/utils/lit/TestRunner.py index 2995196fe41..7b549ac1c61 100644 --- a/utils/lit/TestRunner.py +++ b/utils/lit/TestRunner.py @@ -6,6 +6,7 @@ import Test import Util import platform +import tempfile class InternalShellError(Exception): def __init__(self, command, message): @@ -57,7 +58,11 @@ def executeShCmd(cmd, cfg, cwd, results): assert isinstance(cmd, ShUtil.Pipeline) procs = [] input = subprocess.PIPE - for j in cmd.commands: + stderrTempFiles = [] + # To avoid deadlock, we use a single stderr stream for piped + # output. This is null until we have seen some output using + # stderr. + for i,j in enumerate(cmd.commands): redirects = [(0,), (1,), (2,)] for r in j.redirects: if r[0] == ('>',2): @@ -104,6 +109,14 @@ def executeShCmd(cmd, cfg, cwd, results): else: stderrIsStdout = False + # Don't allow stderr on a PIPE except for the last + # process, this could deadlock. + # + # FIXME: This is slow, but so is deadlock. + if stderr == subprocess.PIPE and j != cmd.commands[-1]: + stderr = tempfile.TemporaryFile(mode='w+b') + stderrTempFiles.append((i, stderr)) + # Resolve the executable path ourselves. args = list(j.args) args[0] = Util.which(args[0], cfg.environment['PATH']) @@ -130,10 +143,10 @@ def executeShCmd(cmd, cfg, cwd, results): else: input = subprocess.PIPE - # FIXME: There is a potential for deadlock here, when we have a pipe and - # some process other than the last one ends up blocked on stderr. + # FIXME: There is probably still deadlock potential here. Yawn. procData = [None] * len(procs) procData[-1] = procs[-1].communicate() + for i in range(len(procs) - 1): if procs[i].stdout is not None: out = procs[i].stdout.read() @@ -144,6 +157,11 @@ def executeShCmd(cmd, cfg, cwd, results): else: err = '' procData[i] = (out,err) + + # Read stderr out of the temp files. + for i,f in stderrTempFiles: + f.seek(0, 0) + procData[i] = (procData[i][0], f.read()) exitCode = None for i,(out,err) in enumerate(procData):