Исчезающий дочерний процесс

У меня есть этот метод:

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). Процесс не работает как зомби, он просто исчезает. В результате второй дочерний процесс зависает и фактически ничего не делает.

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

1

Решение

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

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

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

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

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

1

Другие решения

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

2

По вопросам рекламы [email protected]