2016-01-23 3 views
0

У меня есть функция для запуска процесса, а затем возвращаю код stdout и exit. Однако я заметил, что он утверждает, что каждый процесс возвращает код выхода из 1. Я управляю выведенным исполняемым файлом, и я распечатал его для вывода кода выхода, поэтому я подтвердил, что, когда он «не удался», он фактически возвращается 0 из main. Я также вызвал исполняемый файл непосредственно из оболочки и подтвердил ожидаемый код stdout и exit (0). Таким образом, ошибка должна лежать на стороне вызывающего абонента. Я также подтвердил, что WIFEXITED не возвращает false - он возвращает true, как если бы ребенок нормально выходил (что он и сделал).waitpid() дает неверный код выхода

Этот код работал отлично, прежде чем мне нужно было записать stdout, так что оно должно иметь какое-то отношение к этому. Я попробовал посмотреть, как «Ребенок уже закончил» работу, но это не происходит в этом случае. Waitpid() ведет себя точно так, как я ожидал, и мне все равно, что ребенок, возможно, уже закончил, пока я занимался стандартный вывод.

#include <unistd.h>  
#include <sys/types.h>  
#include <sys/wait.h> 
#include <iostream> 

Wide::Driver::ProcessResult Wide::Driver::StartAndWaitForProcess(std::string name, std::vector<std::string> args, Util::optional<unsigned> timeout) { 
    int filedes[2]; 
    pipe(filedes); 


    pid_t pid = fork(); 

    if (pid == 0) { 
     while ((dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {} 
     freopen("/dev/null", "rw", stdin); 
     freopen("/dev/null", "rw", stderr); 
     //close(filedes[0]); 

     std::vector<const char*> cargs; 

     cargs.push_back(name.c_str()); 

     for (auto&& arg : args) 

      cargs.push_back(arg.c_str()); 

     cargs.push_back(nullptr); 

     execv(name.c_str(), const_cast<char* const*>(&cargs[0])); 

    } 
    std::string std_out; 
    close(filedes[1]); 
    char buffer[4096]; 
    while (1) { 
     ssize_t count = read(filedes[0], buffer, sizeof(buffer)); 
     if (count == -1) { 
      if (errno == EINTR) { 
       continue; 
      } else { 
       perror("read"); 
       exit(1); 
      } 
     } else if (count == 0) { 
      break; 
     } else { 
      std_out += std::string(buffer, buffer + count); 
     } 
    } 
    close(filedes[0]); 

    int status; 
    ProcessResult result; 
    result.std_out = std_out; 
    waitpid(pid, &status, 0); 

    if (!WIFEXITED(status)) 

     result.exitcode = 1; 

    else { 
     result.exitcode = WEXITSTATUS(status); 
     if (result.exitcode != 0) { 
      std::cout << name << " failed with code " << result.exitcode << "\n"; 
      std::cout << "stdout: " << result.std_out; 
     } 
    } 
    return result; 
} 

Почему на земле есть waitpid(), дающий мне этот странный результат и как я могу его исправить?

+0

Код завершения выполняемого процесса находится в тексте 'std_out', а не' result.exitcode'. Отделение печати никогда не выполняется, если 'WIFEXITED (status)' false в любом случае, поэтому мне было бы невозможно распечатать результат этого назначения. – Puppy

+0

Это выглядит довольно подозрительно. 'Const_cast (& cargs [0])' –

+0

Не знаете, почему аргументы должны быть изменены для execve, но я все равно заменяю процесс, поэтому мне не важно состояние памяти вектора. – Puppy

ответ

0

Я подтвердил в IRC, что это проблема LLVM. Код выхода для распечатанного процесса - это то, что я вернулся с main - статический деструктор или другой такой код все еще можно запустить и вызвать exit(1). Это вызвано перенаправлением stderr, поэтому вы не можете получить ошибку, так как если вы не перенаправляете stderr, вы не видите проблему. Поэтому, если вы выполняете из оболочки, поскольку stderr не перенаправляется, все в порядке.

Поэтому, несмотря на скорлупе и мой собственный код возврата соглашаясь, процесс был фактически возвращает код выхода 1.

Видимо проблема решена в багажнике, или должен быть, но я все еще использую 3.6 ,

Смежные вопросы