Перенаправление вывода дочернего процесса

Я перенаправляю вывод от дочернего процесса:

int pipefd[2];
pipe(pipefd);
pid_t pid = fork(); /* Create a child process */

switch (pid) {
case -1: /* Error */
cout << "Uh-Oh! fork() failed.\n";
exit(1);
case 0: /* Child process */
close(pipefd[0]);
dup2(pipefd[1], 1);
dup2(pipefd[1], 2);
close(pipefd[1]);
execv(args[0], (char * const *)args);
cout << "execv() error" << endl;
exit(1);
default: /* Parent process */
close(pipefd[1]);
char buffer[1024];
size_t bytes_read = 0;
bytes_read = read(pipefd[0], buffer, sizeof(buffer));
if(bytes_read == -1) {
cout << "read() error" << endl;
exit(1);
}

close(pipefd[0]);

if(bytes_read > 0) {
buffer[bytes_read-1] = '\0'; // Overwrite the newline
}

int status, exit_pid;
while(true) {
exit_pid = waitpid(pid, &status, 0);
if(exit_pid == -1) {
cout << "waitpid() error: " << strerror(errno) << endl;
exit(1);
}
else {
return WEXITSTATUS(status);
}
}
}

Это прекрасно работает, когда я запустил его как изолированный кусок кода. Но когда я интегрирую его в мою многопоточную среду, происходит ужасная вещь: вызовы read () каким-то образом считывают выходные данные других потоков родительского процесса, как если бы это был выход из канала дочернего процесса.
Кто-нибудь сталкивался с такой вещью?
Я на OS X.

-1

Решение

Ну, у меня есть решение, хотя я не совсем понимаю, почему это произошло.

Но сначала должно быть ясно, что такое поведение не является ни нормальным, ни ожидаемым. Дочерний процесс, созданный с помощью fork (), не наследует никаких запущенных потоков от своего родителя (поэтому неожиданный вывод должен исходить из родительских потоков). И у него есть собственная таблица дескрипторов. Поэтому, когда дочерний процесс вызывает dup2 () для изменения своих выходных дескрипторов, это не должно иметь никакого влияния на потоки в родительском процессе.

Проблема возникала только в тех случаях, когда вызов execv () не удался. В этих случаях я ожидал, что завершение дочернего процесса закроет все его файловые дескрипторы. Но этого не произошло, или, по крайней мере, он не имел такого же эффекта, как явный вызов close (). Поэтому добавление явных вызовов close () после execv () решило проблему:

execv(args[0], (char * const *)args);
close(1);
close(2);
exit(1);

Закрытие дескриптора конца записи канала приводит к тому, что операция чтения на конце чтения получает 0, таким образом зная, что больше не читает.
Тем не менее, я до сих пор не знаю следующее:

  1. Почему вызов exit () в дочернем процессе не эквивалентен явному вызову close ()?
  2. Даже если конец записи канала не закрыт, почему чтение из конца чтения приводит к выводу потоков в родительском процессе вместо блокировки или возврата какой-либо ошибки?

Если кто-то может пролить свет на это, это будет оценено.

0

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector