У меня есть Perl-скрипт (фрагмент ниже), который запускается в cron для выполнения системных проверок.Я разрываю ребенка как тайм-аут и пожинаю его с помощью SIG {CHLD}.Perl выполняет несколько системных вызовов скриптов Bash и проверяет их состояние выхода.Один сценарий bash дает сбой около 5% времени без ошибок.Сценарии Bash существуют с 0, а Perl видит $?как -1 и $!как "Нет дочерних процессов".
Этот сценарий bash проверяет лицензии компилятора, а Intel icc остается после завершения сценария Bash (вывод ps ниже).Я думаю, что icc zombie завершает работу, заставляя Perl использовать обработчик SIG {CHLD}, который уничтожает $?статус, прежде чем я смогу его прочитать.
Compile status -1; No child processes
#!/usr/bin/perl
use strict;
use POSIX ':sys_wait_h';
my $GLOBAL_TIMEOUT = 1200;
### Timer to notify if this program hangs
my $timer_pid;
$SIG{CHLD} = sub {
local ($!, $?);
while((my $pid = waitpid(-1, WNOHANG)) > 0)
{
if($pid == $timer_pid)
{
die "Timeout\n";
}
}
};
die "Unable to fork\n" unless(defined($timer_pid = fork));
if($timer_pid == 0) # child
{
sleep($GLOBAL_TIMEOUT);
exit;
}
### End Timer
### Compile test
my @compile = `./compile_test.sh 2>&1`;
my $status = $?;
print "Compile status $status; $!\n";
if($status != 0)
{
print "@compile\n";
}
END # Timer cleanup
{
if($timer_pid != 0)
{
$SIG{CHLD} = 'IGNORE';
kill(15, $timer_pid);
}
}
exit(0);
#!/bin/sh
cc compile_test.c
if [ $? -ne 0 ]; then
echo "Cray compiler failure"
exit 1
fi
module swap PrgEnv-cray PrgEnv-intel
cc compile_test.c
if [ $? -ne 0 ]; then
echo "Intel compiler failure"
exit 1
fi
wait
ps
exit 0
Ожидание на самом деле не ждет, потому что cc вызывает icc, который создает процесс внука зомби, который ждет (или ждать PID) нене блокировать для.(подождите `pidof icc`, 31589 в данном случае, выдает" не дочерний элемент этой оболочки ")
user 31589 1 0 12:47 pts/15 00:00:00 icc
Я просто не знаю, как это исправить в Bash или Perl.
Спасибо, Крис