Привет.Заметил что waitpid() для _завершившегося_ потомка,
который стартовал через новую сессию (fork() -> setsid() -> execve())
всегда возвращает ECHILD (No child processes).
В то же время, сигнал SIGCHLD исправно доставляется родителю.
Т.е. получается, что "оперившийся" с помощью setsid() потомок
становится как бы почти взрослым :-)
и получить статус его завершения или убивший его сигнал
(причём нельзя узнать что именно) можно только через sighanler (siginfo_t).
Повторюсь, waitpid() запускается когда потомок уже завершился.Не могу найти где такое поведение явно прописано (если только я чего не напутал)
и желательно с ссылками на стандарт (POSIX, SVR, BSD).Linux/2.6
>Т.е. получается, что "оперившийся" с помощью setsid() потомок
>становится как бы почти взрослым :-)Проверил на минимальной реализации, не подтверждается.
wait получает pid потомка, даже если тот успешно сделал setsid.
Так что либо ошибка где-то, либо особенность Linux.$ uname -sr
Darwin 9.6.0
>wait получает pid потомка, даже если тот успешно сделал setsid.
>$ uname -sr
>Darwin 9.6.0Уверены, что waitpid() запускали уже _после_ завершения потомка?
>>wait получает pid потомка, даже если тот успешно сделал setsid.
>>$ uname -sr
>>Darwin 9.6.0
>
>Уверены, что waitpid() запускали уже _после_ завершения потомка?Да.
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>int main(int argc, const char *argv[]) {
sigset_t newmask, oldmask, waitmask;
pid_t pid_fork, pid_wait;
int stat;sigfillset(&newmask);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
perror("sigprocmask");
return 0;
}
pid_fork = fork();
if(pid_fork == -1) {
perror("fork");
return 0;
}
else if(pid_fork != 0) {
sigemptyset(&waitmask);
sigaddset(&waitmask, SIGCHLD);
sigsuspend(&waitmask);
pid_wait = waitpid(pid_fork, &stat, 0);
printf("fork returned %d, waitpid returned %d\n", pid_fork, pid_wait);
return 0;
}
else {
if(setsid() == -1) {
perror("setsid");
return 0;
}
return 0;
}
}