[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