Only tee stdin if a "-" was passed the compiler.

This allows to remove the workaround in env.Run,
and fixes the bug in the workaround that it didn't
return exit code errors correctly.

BUG=chromium:773875
TEST=manually tested in the chroot.

Change-Id: I486b30b65ba3ad6249aa89e82e292c66378187a2
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1762345
Tested-by: Tobias Bosch <tbosch@google.com>
Reviewed-by: George Burgess <gbiv@chromium.org>
diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go
index ad66f99..bbb7434 100644
--- a/compiler_wrapper/compiler_wrapper.go
+++ b/compiler_wrapper/compiler_wrapper.go
@@ -44,7 +44,7 @@
 	stdinBuffer := &bytes.Buffer{}
 	recordingEnv := &commandRecordingEnv{
 		env:         env,
-		stdinReader: io.TeeReader(env.stdin(), stdinBuffer),
+		stdinReader: teeStdinIfNeeded(env, inputCmd, stdinBuffer),
 	}
 	// Note: this won't do a real exec as recordingEnv redirects exec to run.
 	if exitCode, err = callCompilerInternal(recordingEnv, cfg, inputCmd); err != nil {
@@ -200,3 +200,17 @@
 			compilerErr)
 	}
 }
+
+func teeStdinIfNeeded(env env, inputCmd *command, dest io.Writer) io.Reader {
+	// We can't use io.TeeReader unconditionally, as that would block
+	// calls to exec.Cmd.Run(), even if the underlying process has already
+	// terminated. See https://github.com/golang/go/issues/7990 for more details.
+	lastArg := ""
+	for _, arg := range inputCmd.Args {
+		if arg == "-" && lastArg != "-o" {
+			return io.TeeReader(env.stdin(), dest)
+		}
+		lastArg = arg
+	}
+	return env.stdin()
+}