Невозможно игнорировать сигнал 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);