Сделать дочерний процесс не зомби до ожидания

Существует ли метод Linux или POSIX для указания процессу не превращаться в зомби, когда он завершается, а родитель не вызывает waitpid()?

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

Есть ли способ пометить конкретный дочерний процесс, чтобы он просто тихо умер сам по себе, если меня не интересует код выхода?


person Jeroen    schedule 13.03.2017    source источник


Ответы (1)


Вам всегда нужно будет ждать дочерний процесс, однако, если вы будете следовать этой процедуре, вы можете дождаться дочернего процесса, который быстро умрет, и позволить init унаследовать ваш «настоящий» процесс. Затем Init уберет за вас.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

void main(void) {
    int ret;
    pid_t child1;
    pid_t child2;
    int status;

    child1 = fork();
    if (child1 == -1) {
        /* error */
        exit(1);
    }

    if (child1 == 0) {
        /* in the child... we create a new session, and then re-fork */
        setsid();

        child2 = fork();
        if (child2 == -1) {
            exit(1);
        }

        if (child2 == 0) {
            /* call execve() or a friend */
            ret = execlp("sleep", "sleep", "6", NULL);

            /* we should _never_ get here - unless the execlp() fails */
            fprintf(stderr, "execlp() returned: %d\n", ret);
            exit(1);
            for(;;);
        }

        sleep(2); 

        /* success ... child1 dies here */
        exit(0);
    }

    sleep(4);

    ret = waitpid(child1, &status, 0);
    if (ret != 0) {
        /* unfortunately we can only determine the state of our 'proxy' process...
         * to get any further information / the child-child PID, then you'll need to use a pipe to share the information */
        fprintf(stderr, "waitpid() returned %d\n", ret);
    }

    sleep(4); 

    return;
}

Различная продолжительность сна должна позволить вам увидеть следующие события (смотреть top или что-то в этом роде).

Шаг 1

Все процессы запускаются, все связаны как дочерние элементы вашей оболочки

  • 17336 - Моя оболочка
  • 21855 - Приложение
  • 21856 - Child1 (прокси-процесс)
  • 21857 - Child2 (полезный дочерний процесс)

top вывод:

attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
attie    21856 21855  0 16:34 ?        00:00:00 ./test
attie    21857 21856  0 16:34 ?        00:00:00 sleep 6

Шаг 2

Child1 умирает и становится зомби/несуществующим, Child2 наследуется init (PID 1)

attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
attie    21856 21855  0 16:34 ?        00:00:00 [test] <defunct>
attie    21857     1  0 16:34 ?        00:00:00 sleep 6

Шаг 3

Child1 очищается родителем при вызове waidpid()

attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
attie    21857     1  0 16:34 ?        00:00:00 sleep 6

Шаг 4

Child2 умирает и очищается init

attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
person Attie    schedule 13.03.2017