URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 7831
[ Назад ]

Исходное сообщение
"waitpid() для потомка который сделал setsid() "

Отправлено devcoder , 14-Янв-09 18:46 
Привет.

Заметил что waitpid() для _завершившегося_ потомка,
который стартовал через новую сессию (fork() -> setsid() -> execve())
всегда возвращает ECHILD (No child processes).
В то же время, сигнал SIGCHLD исправно доставляется родителю.
Т.е. получается, что "оперившийся" с помощью setsid() потомок
становится как бы почти взрослым :-)
и получить статус его завершения или убивший его сигнал
(причём нельзя узнать что именно) можно только через sighanler (siginfo_t).
Повторюсь, waitpid() запускается когда потомок уже завершился.

Не могу найти где такое поведение явно прописано (если только я чего не напутал)
и желательно с ссылками на стандарт (POSIX, SVR, BSD).

Linux/2.6


Содержание

Сообщения в этом обсуждении
"waitpid() для потомка который сделал setsid() "
Отправлено Michelnok , 21-Янв-09 03:57 
>Т.е. получается, что "оперившийся" с помощью setsid() потомок
>становится как бы почти взрослым :-)

Проверил на минимальной реализации, не подтверждается.
wait получает pid потомка, даже если тот успешно сделал setsid.
Так что либо ошибка где-то, либо особенность Linux.

$ uname -sr
Darwin 9.6.0


"waitpid() для потомка который сделал setsid() "
Отправлено devcoder , 21-Янв-09 11:53 
>wait получает pid потомка, даже если тот успешно сделал setsid.
>$ uname -sr
>Darwin 9.6.0

Уверены, что waitpid() запускали уже _после_ завершения потомка?



"waitpid() для потомка который сделал setsid() "
Отправлено Michelnok , 21-Янв-09 15:10 
>>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;
    }
}