Если процесс внука завершается, будет ли он обработан функцией wait () в родительском процессе или в процессе прародителя? - PullRequest
0 голосов
/ 15 апреля 2020

Прежде всего, позвольте мне объяснить, как я могу придумать этот вопрос. Мой код выглядит так:

void *foo(void *data)
{
    printf("foo pid %d\n", getpid());
    sleep(2);
    int res = system("echo haha");
    printf("System result: %d\n", res);
    return NULL;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, NULL, foo, NULL);
    int wstatus;
    int p;
    do {
        p = waitpid(-1, &wstatus, 0);
        if (p == -1) {
            // This prints a bunch of "Errno 10 No child processes"
            //printf("Errno %d %s\n", errno, strerror(errno));
        } else {
            break;
        }
    } while (1);
    printf("Exited process: %d\n", p);
}

Я ожидаю, что system() всегда будет возвращать 0. Однако программа дает мне один из этих сценариев ios:

foo pid 8793

хаха

Системный результат: 0

и

foo pid 8685

хаха

Выход из процесса: 8687

Системный результат: -1

На основании "man system" , говорят, что

  • Если дочерний процесс не может быть создан или его состояние не может быть получено, возвращаемое значение равно -1.

Поскольку дочерний процесс всегда создается ("echo haha" в обоих случаях завершается успешно), я предполагаю, что завершение дочернего процесса, созданного в вызове system(), случайно выбирается либо waitpid(), либо system(), что означает, что system() возвращает 0, то waitpid() возвращает -1, а если system() возвращает -1, что означает, что ему не удалось получить идентификатор своего дочернего процесса, то waitpid() возвращает идентификатор процесса, созданного system(). * 10 45 *

На основании моего исследования system() фактически вызывает fork(), execl() и waitpid() в его реализации. Итак, мой вопрос: если system() вызывает waitpid(), то как получается, что завершение его дочернего процесса воспринимается процессом "прародителя", а не им самим? Если я сам реализую system(), будет ли это иметь какое-то значение?

ОБНОВЛЕНИЕ

Видимо, ответ - , завершение дочернего процесса всегда происходит по вызову waitpid() его «прямого» родительского процесса и, как предполагает ссылка , нет никакого способа для процесса напрямую wait() для своих процессов-внуков . Таким образом, вопрос теперь больше похож на «как звонит system() ведет себя так?».

ОБНОВЛЕНИЕ 2

Похоже, я неправильно понимаю system(). Код выше в основном вызывает waitpid() в двух потоках - основной поток и внутри foo() (который вызывает system()). Таким образом, есть два потока, которые вызывают waitpid() одновременно, и только один из них завершается успешно.

...