2014-10-06 3 views
1

У меня есть этот метод:Исчезновение дочерний процесс

int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc) { 
    std::cout << "Building Pipe...\ncmd1: " << cmd1 << "\n cmd2: " << cmd2 << "\n"; 
    int *pipefd = new int[2]; 
    if (pipe(pipefd) < 0) { 
     std::cerr << "There was an error setting up the pipe.\n"; 
     return -1; 
    } 
    pid_t cpid1 = fork(); 
    std::cout << "First process forked, cpid: " << cpid1 << " - Process " << getpid() << "\n"; 
    switch (cpid1) { 
     case -1: 
      std::cerr << "There was an error forking the process.\n"; 
      return -1; 
      break; 
     case 0: // this is the part that isn't executing 
      std::cout << "Dup2 return: " << dup2(pipefd[1], 1) << "\n"; 
      std::cout << "Process " << getpid() << " duped and about to exec.\n"; 
      execvp(cmd1.c_str(), argv1); 
      std::cout << "Process " << getpid() << " about to exit.\n"; 
      _exit(0); 
      break; 
     default: 
      pid_t cpid2 = fork(); 
      switch (cpid2) { 
       case -1: 
        std::cerr << "There was an error forking the process.\n"; 
        return -1; 
        break; 
       case 0: 
        dup2(pipefd[0], 0); 
        std::cout << "Process " << getpid() << " duped and about to exec.\n"; 
        execvp(cmd2.c_str(), argv2); 
        _exit(0); 
        break; 
       default: 
        if (conc) { 

        } else { 
         int status1, status2; 
         std::cout << "Process " << getpid() << " about to wait.\n"; 
         waitpid(cpid1, &status1, 0); 
         waitpid(cpid2, &status2, 0); 
        } 
        break; 
      } 
     } 
    delete[] pipefd; 
    return 0; 
} 

Я добавил операторы печати исключительно для целей отладки. Однако, когда этот метод работает, это то, что печатается.

Building Pipe... 
cmd1: cat 
cmd2: wc 
First process forked, cpid: 1454 - Process 1453 
First process forked, cpid: 0 - Process 1454 
Process 1453 about to wait. 
Process 1455 duped and about to exec. 

Процесс 1454, первый процесс раздвоенного, печатает сообщение сразу после его создания. Тем не менее, он никогда не печатает ни одно из сообщений из оператора switch и никогда не выполняет указанную программу (в данном случае cat). Процесс не висит вокруг как зомби, он просто исчезает. В результате второй дочерний процесс зависает и никогда ничего не делает.

(также, просто для добавления, я знаю, что я еще не добавил всю необходимую обработку ошибок, функция еще не завершена).

+0

'int * pipefd = new int [2];' действительно? –

+0

Не могли бы вы дать нам [минимальный полный пример] (http://stackoverflow.com/help/mcve)? Мы не знаем всех аргументов, которые вы передаете, и я сомневаюсь, что весь этот код необходим для воспроизведения проблемы. – Beta

ответ

1

трубопровод заканчивается, когда он обнаруживает EOF и для этого необходимо закрыть ненужные дескрипторы, как только вы dupped его (в детей и родителей):

close(pipefd[0]); 
close(pipefd[1]); 

Кроме того, всегда проверять возвращение значение execvp, вы можете иметь ошибку в ARGV'S:

if (execvp(cmd1.c_str(), argv1) == -1) { 
    // check errno here 
} 

Кроме того, убедитесь, чтобы положить конец ARGV с nullptr, как последний элемент, и argv [0] должен быть самой командой. Прототип:

int build_pipe_and_call(char **argv1, std::string cmd1, char **argv2, std::string cmd2, int conc) 

... заставляет меня думать, что вы не обеспечивают первый элемент (ARGV [0] = cmd1). Вам не нужно было бы указывать эту дополнительную стоимость (cmdX) для работы build_pipe_and_call, если у вас ее есть в argv.

Помните, что если execvp идет хорошо, вы никогда не достигнете последующего кода в вашей программе, так что вы не будете видеть некоторые сообщения, как вы могли бы ожидать:

execvp(cmd1.c_str(), argv1); 
std::cout << "Process " << getpid() << " about to exit.\n"; // if execvp didn't fail, it's never reached 

Также будьте осторожны, чтобы использовать зЬй :: cout, как только вы его обманули, поскольку @larpico answered

2

Вы не видите сообщения из инструкции switch, потому что они были записаны в трубу. Попробуйте заменить std::cout на std::cerr.

+0

Ежедневное напоминание, что я идиот. Спасибо вам за это. Теперь вопрос меняется на то, что я делаю неправильно в отношении трубы. –

+1

@ NickDell'osa: ответ на это в [jaba10] (http://stackoverflow.com/users/4095830/jaba10) [ответ] (http://stackoverflow.com/a/26209490/15168) , –

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