diff options
author | Kuba Brecka <kuba.brecka@gmail.com> | 2016-04-11 09:27:09 +0000 |
---|---|---|
committer | Kuba Brecka <kuba.brecka@gmail.com> | 2016-04-11 09:27:09 +0000 |
commit | 12d2fe2a170a5be91dddef5555b7f21a36e3a704 (patch) | |
tree | 2ae74cb1a2ef6f825ba54ed522ea2f83a4896b65 /lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc | |
parent | 85b89ec3da7a0154211a1345cd6e23f980f5666e (diff) |
[sanitizer] Restore stderr when using forkpty() to spawn external symbolizer
In `AtosSymbolizer`, we're using `forkpty()` to create a new pseudo-terminal to communicate with the `atos` tool (we need that to avoid output buffering in interactive mode). This however redirects both stdout and stderr into a single stream, so when we read the output, we can't distinguish between errors and standard replies. Let's save&restore stderr to avoid that.
Differential Revision: http://reviews.llvm.org/D15073
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@265923 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index e84fef09f..7de3dbd08 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -74,6 +74,13 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { if (use_forkpty_) { #if SANITIZER_MAC fd_t fd = kInvalidFd; + + // forkpty redirects stdout and stderr into a single stream, so we would + // receive error messages as standard replies. To avoid that, let's dup + // stderr and restore it in the child. + int saved_stderr = dup(STDERR_FILENO); + CHECK_GE(saved_stderr, 0); + // Use forkpty to disable buffering in the new terminal. pid = internal_forkpty(&fd); if (pid == -1) { @@ -83,6 +90,11 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { return false; } else if (pid == 0) { // Child subprocess. + + // Restore stderr. + CHECK_GE(dup2(saved_stderr, STDERR_FILENO), 0); + close(saved_stderr); + const char *argv[kArgVMax]; GetArgV(path_, argv); execv(path_, const_cast<char **>(&argv[0])); @@ -92,6 +104,8 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { // Continue execution in parent process. input_fd_ = output_fd_ = fd; + close(saved_stderr); + // Disable echo in the new terminal, disable CR. struct termios termflags; tcgetattr(fd, &termflags); |