Невозможно игнорировать сигнал CHLD, форсируя значение по умолчанию

 #include <sys/types.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <sys/wait.h>
 #include <signal.h>
 #include <iostream>
 #include <unistd.h>
 int main(){


        signal(SIGCHLD,SIG_IGN );
        pid_t pid  = vfork();
        if(pid <0){
            std::cout<< "Error: Fork failed at main!!!";
            exit(1);
        }else if (0 == pid){


            char * cmd[] ={(char*)"../work/C++11/Prj_LargeFile/script/Logger.pl",NULL};
            //char * cmd[] = {(char*)"pwd",NULL};
            //char * cmd[] = {(char*)"/usr/bin/perl",(char*)"../work/C++11/Prj_LargeFile/script/Logger.pl",NULL};

            execvp(cmd[0],cmd);


             _exit(0);
        }
}

Я хочу иметь дочерний процесс-сироту, который будет запускать Perl-скрипт в backgroud, и хочу, чтобы родительский процесс завершился, не дожидаясь своего дочернего процесса. Поэтому в начале я использовал сигнал (SIGCHLD,SIG_IGN), чтобы игнорировать дочерний сигнал по завершении и избегать зомби. Но когда я запускаю код, он выдаёт мне ошибку, так как не может игнорировать сигнал CHLD, что приводит к дефолту., С другой стороны, когда я запускаю эти закомментированные строки, вместо этого он работает с нужным сигналом. в чем причина этого?

1 ответ

Perl выдает это предупреждение. Похоже, что последние версии glibc (или, возможно, определенных опций в ядре Linux) убрали возможность игнорировать SIGCHLD, насколько это касается Perl. Я не знаю, почему это так, но я столкнулся с этим в системе, которая раньше была счастлива игнорировать SIGCHLD.

В соответствии с perldoc perlipc, который вы обязательно должны посмотреть для получения дополнительной информации, лучше всего обратиться к этому:

use POSIX ":sys_wait_h"; # for nonblocking read
$SIG{CHLD} = sub {
    while ((my $child = waitpid(-1, WNOHANG)) > 0) {
        # $Kid_Status{$child} = $?;
    }
};
# do something that forks...

Линия с $Kid_Status взято из оригинального perldoc, но я прокомментировал его, потому что цель состоит в том, чтобы игнорировать дочерние процессы, и я хотел прояснить, что внутри while не должен содержать никакого кода. Существует множество способов обратиться к обработке дочерних процессов в perldoc, например, если ваш Perl-скрипт предназначен для демонизации или если вы намереваетесь exec или же die в обработчике.

Если вы не можете редактировать Perl-скрипт, который вы вызываете, я рекомендую напечатать строку STDERR прямо перед execvp говорит пользователю игнорировать ложное предупреждение. Например,

fputs("The next line is a harmless warning.\n", stderr);
Другие вопросы по тегам