forked from OSchip/llvm-project
[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 llvm-svn: 265923
This commit is contained in:
parent
716a533a7f
commit
036d060044
|
@ -79,23 +79,6 @@ class AtosSymbolizerProcess : public SymbolizerProcess {
|
|||
char pid_str_[16];
|
||||
};
|
||||
|
||||
static const char *kAtosErrorMessages[] = {
|
||||
"atos cannot examine process",
|
||||
"unable to get permission to examine process",
|
||||
"An admin user name and password is required",
|
||||
"could not load inserted library",
|
||||
"architecture mismatch between analysis process",
|
||||
};
|
||||
|
||||
static bool IsAtosErrorMessage(const char *str) {
|
||||
for (uptr i = 0; i < ARRAY_SIZE(kAtosErrorMessages); i++) {
|
||||
if (internal_strstr(str, kAtosErrorMessages[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
|
||||
char **out_module, char **out_file, uptr *line,
|
||||
uptr *start_address) {
|
||||
|
@ -112,12 +95,6 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
|
|||
// 0xdeadbeef (in library.dylib)
|
||||
// 0xdeadbeef
|
||||
|
||||
if (IsAtosErrorMessage(trim)) {
|
||||
Report("atos returned an error: %s\n", trim);
|
||||
InternalFree(trim);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *rest = trim;
|
||||
char *symbol_name;
|
||||
rest = ExtractTokenUpToDelimiter(rest, " (in ", &symbol_name);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue