Проверка на наличие завершенных дочерних процессов в POSIX?

#c #posix #child-process #waitpid

#c #posix #дочерний процесс #waitpid

Вопрос:

Я пытаюсь написать программу, которая проверяет наличие завершенных дочерних процессов и перезапускает их, если они завершились. Необходимо перезапускать процессы по мере их завершения, не дожидаясь завершения каких-либо других процессов. Я немного заблудился. Вот код, который я уже сделал. На самом деле это не закончено или не корректно. Но, возможно, кто-нибудь может указать мне правильное направление?

 for(int ifile = 1; ifile < 4; ifile  ){

    child_pid[ifile - 1] = vfork();

    if(child_pid[ifile - 1] == -1){
        cerr << "fork error on " << argv[ifile] << endl;
    }
    else if(child_pid[ifile - 1] == 0){
        execl(argv[ifile], argv[ifile], NULL);
    }
}

for(int index = 0; index < 3; index  ){
    do{
        wait_pid = waitpid(child_pid[index], amp;status, WUNTRACED);
        if(WIFEXITED(status)){
            count  ;
            child_pid[index] = vfork();
            if(child_pid[index] == -1){
                cerr << "rescheduled process error" << endl;
                return -1;
            }
            else if(child_pid[index] == 0){
                cout << "Rescheduling " << argv[index   1] << endl;
                execl(argv[index   1], argv[index   1], NULL);
            }
        }
    }while(count != 4);
}
  

Ответ №1:

Проблема с вашим подходом заключается в том, что вы собираетесь блокировать waitpid до тех пор, пока этот 1-й [0-й] дочерний процесс не умрет, а любой из других может умереть за это время.

Вы можете:

(1) Используйте wait() вместо waitpid(). Это обработает любой из дочерних процессов, но он будет заблокирован.

(2) опрос на предмет мертвых дочерних процессов с использованием waitpid() и флага WNOHANG во время выполнения цикла.

(3) Настройте обработчик сигналов и перехватывайте сигналы SIGCHILD. Поместите цикл waitpid / WNOHANG в свой обработчик, но выполните перезапуск вне его.

Например, обработчик выполняет что-то вроде:

    while ((child_pid = waitpid(-1, amp;status, WNOHANG)) > 0) 
   {
        //set a flag or whatever; not wise to fork/exec in handler
   }
  

Ответ №2:

Я не уверен, зачем вам нужна эта WUNTRACED опция. Там, где написано «Остановлено», я почти уверен, что это означает то же самое, что приостановлено, а не завершено.

Два возможных подхода:

Вместо зацикливания просто выполните:

 pid_t pid = wait();
  

он будет блокироваться до тех пор, пока процесс не завершится.

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