Как контролировать выполнение родительского процесса после вызова execl() в программе C?

У меня есть простая программа на C, которая выполняет приложение, используя fork() и execl(). Если execl() не удается запустить приложение, мне нужно вызвать функцию в родительском процессе и выйти из дочернего процесса. Если execl() успешно запускает приложение, я показываю журнал успеха из родительского процесса. Итак, родительский процесс должен дождаться вызова execl() дочернего процесса (именно вызова, а не до конца выполнения приложения), получить некоторую информацию о его статусе, а затем принять решение и продолжить собственное выполнение. Вот мой код.

int main()
{
    int iExecRetVal, pid;
    pid = fork();

    if (pid == -1)
    {

    }
    else if (pid > 0)
    {
    }
    else
    {
        iExecRetVal = execl("./flute-static", "./flute-static", "-send", "-a192.168.190.1/6666", "JFlute.1.2.tar.gz", NULL);
        if (iExecRetVal == -1)
        {
            /*execl() failed, need some error handling in the parent process*/
        }
        _exit(0);
    }

    /*Parent's normal execution*/
}

int HandleSuccessFromParent()
{
    /*Should be called when exec call was successful*/
}

int HandleFailureFromParent()
{
    /*Should be called when exec call was NOT successful*/
}

Мы знаем, что execl() не возвращает результат в случае успеха. Итак, как правильно вызывать функции HandleSuccessFromParent() и HandleFailureFromParent() после вызова execl() в дочернем элементе. Пожалуйста помогите.


person JatiA    schedule 28.10.2014    source источник


Ответы (2)


Дочерний процесс должен завершиться со статусом ошибки (ненулевым; 1 является общим, EXIT_FAILURE является стандартным C).

Родительский процесс должен дождаться завершения дочернего процесса и зафиксировать статус завершения дочернего процесса, используя wait() или waitpid().

Если вам нужно знать, умер ли дочерний элемент, но не хотите ждать его завершения, используйте waitpid() с WNOHANG после небольшой паузы, чтобы позволить дочернему элементу попытаться запуститься (задержка в доли секунды, вероятно, будет достаточной).

person Jonathan Leffler    schedule 28.10.2014
comment
IIRC, system(3) будет _exit(127), если ее execve из /bin/sh терпит неудачу, поэтому в Linux или Posix я думаю, что в этом случае полезно использовать код выхода 127 (я не знаю ни одной программы, выходящей из 127 в других случаях) - person Basile Starynkevitch; 28.10.2014
comment
@BasileStarynkevitch: Да, и спецификация POSIX sh включает информация о значениях состояния выхода 126, 127 и 129+ для различных условий ошибки в оболочках. Вы можете решить следовать этому, если хотите. Важным моментом является «не выходить со статусом 0 в случае сбоя»; выход с 126, 127 и т. д. является усовершенствованием второго порядка. - person Jonathan Leffler; 29.10.2014
comment
Действительно, это уточнение, но весьма полезное. GNU grep использует несколько (небольших) кодов выхода при сбое, поэтому использование чего-то другого, кроме 1, полезно, а использование 127 немного полезнее (поскольку в этом случае это обычная привычка). - person Basile Starynkevitch; 29.10.2014
comment
Спасибо. Я использую waitpid() в родительском с помощью WNOHANG. До этого я использую сон (1). Он отлично работает, когда дочерний процесс достаточно длинный. Но когда дочерний процесс завершается нормально (без EXIT_FAILURE) в течение короткого промежутка времени (вероятно, ‹ 1 секунды), он возвращает -1. Как это исправить? - person JatiA; 29.10.2014
comment
Используйте сон в доли секунды — nanosleep() или, может быть, usleep(), или, возможно, select(), или... Чтобы определить, собирается ли ребенок выйти, вам, вероятно, нужно поспать всего несколько миллисекунд; целая секунда - это перебор. - person Jonathan Leffler; 26.02.2016

Одно из возможных решений включает ptrace. Схема выглядит следующим образом:

Пусть ребенок назовет ptrace(PTRACE_TRACEME). Позвольте родителю включить опцию PTRACE_O_TRACEEXEC и waitpid для дочернего элемента. В этой настройке waitpid вернется после успешного execl. Проверьте статус, чтобы увидеть, установлен ли для него флаг SIGTRAP. Пусть ребенок продолжит с PTRACE_DETACH.

person user58697    schedule 28.10.2014
comment
Верно, но, вероятно, слишком высокотехнологично для большинства из нас. На практике я предпочитаю ответ Джонатана Леффлера. - person Basile Starynkevitch; 29.10.2014