diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc --- a/llvm/lib/Support/Unix/Signals.inc +++ b/llvm/lib/Support/Unix/Signals.inc @@ -432,6 +432,10 @@ } void llvm::sys::DefaultOneShotPipeSignalHandler() { + // UNIX03 conformance requires a non-zero exit code and an error message + // to stderr when writing to a closed stdout fails. + errs() << "error: write on a pipe with no reader\n"; + // Send a special return code that drivers can check for, from sysexits.h. exit(EX_IOERR); } diff --git a/llvm/test/Support/unix03-sigpipe-exit.test b/llvm/test/Support/unix03-sigpipe-exit.test new file mode 100644 --- /dev/null +++ b/llvm/test/Support/unix03-sigpipe-exit.test @@ -0,0 +1,26 @@ +## Test that when writing to a closed stdout, LLVM tools finish with a non-zero +## exit code and an error message on stderr. The test uses llvm-cxxfilt, but +## it's a logic from the default SIGPIPE handler, so it applies to all the tools. +## This is required for UNIX03 conformance. + +# UNSUPPORTED: system-windows + +# RUN: not %python %s llvm-cxxfilt 2>&1 | FileCheck %s +# CHECK: error: write on a pipe with no reader + +import subprocess +import sys + +with subprocess.Popen([sys.argv[1]], stdout=subprocess.PIPE, stdin=subprocess.PIPE) as process: + process.stdout.close() + + # llvm-cxxfilt with no extra arguments runs interactively and writes input + # to output. Writing continuously to stdin should trigger SIGPIPE when the + # subprocess attempts to write out bytes to a closed stdout. + try: + while True: + process.stdin.write("foo\n".encode("utf-8")) + except BrokenPipeError: + # Clear stdin, pipe is broken and closing it on cleanup will raise an exception. + process.stdin = None +sys.exit(process.returncode)