summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
diff options
context:
space:
mode:
authorKuba Brecka <kuba.brecka@gmail.com>2016-04-11 09:27:09 +0000
committerKuba Brecka <kuba.brecka@gmail.com>2016-04-11 09:27:09 +0000
commit12d2fe2a170a5be91dddef5555b7f21a36e3a704 (patch)
tree2ae74cb1a2ef6f825ba54ed522ea2f83a4896b65 /lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
parent85b89ec3da7a0154211a1345cd6e23f980f5666e (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.cc14
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);