Закройте любые открытые проекты, которые не находятся в текущем употреблении.
Попытка выключить автоматическое публикуют режим во время разработки.
Вот второй ответ, который касается случая тайм-аута второго процесса. Используйте этот случай для запуска вашей внешней программы и убедитесь, что это не займет слишком много времени:
my $timeout = 180;
my $pid = fork;
if ( defined $pid ) {
if ( $pid ) {
# this is the parent process
local $SIG{ALRM} = sub { die "TIMEOUT" };
alarm 180;
# wait until child returns or timeout occurs
eval {
waitpid( $pid, 0 );
};
alarm 0;
if ( $@ && $@ =~ m/TIMEOUT/ ) {
# timeout, kill the child process
kill 9, $pid;
}
}
else {
# this is the child process
# this call will never return. Note the use of exec instead of system
exec "simulator --shell";
}
}
else {
die "Could not fork.";
}
Вы можете установить сигнал тревоги, который сработает в вашем коде через указанное количество секунд:
eval {
local $SIG{ ALRM } = sub { die "TIMEOUT" };
alarm 3 * 60;
for (my $i = 0 ; $i <$QUOTA ; $i++) {
build_dyna_file($i);
comp_simu_exe;
bin2txt2errormap($i);
}
alarm 0;
};
if ( $@ && $@ =~ m/TIMEOUT/ ) {
warn "operation timed out";
}
else {
# somebody else died
alarm 0;
die $@;
}
Или, если вам действительно нужно, чтобы цикл запускался как минимум три раза, независимо от того, сколько времени это может занять:
eval {
my $t0 = time;
local $SIG{ ALRM } = sub { die "TIMEOUT" };
for (my $i = 0 ; $i <$QUOTA ; $i++) {
build_dyna_file($i);
comp_simu_exe;
bin2txt2errormap($i);
if ( $i == 3 ) {
my $time_remaining = 3 * 60 - time - $t0;
alarm $time_remaining if $time_remaining > 0;
}
}
alarm 0;
};
В Perl вы справляетесь с тайм-аутами, подобными этому, с помощью функции alarm
. Он отправит сигнал ALRM
вашему процессу по прошествии количества секунд, которое вы ему дадите. Будьте осторожны, если в коде вы пытаетесь установить тайм-аут для вызовов sleep
, так как они плохо сочетаются на многих платформах. Базовая структура выглядит так:
#start a block eval to stop the die below from ending the program
eval {
#set the signal handler for the ALRM signal to die if it is run
#note, the local makes this signal handler local to this block
#eval only
local $SIG{ALRM} = sub { die "timeout\n" };
alarm $wait; #wait $wait seconds and then send the ALRM signal
#thing that could take a long time
alarm 0; #turn off the alarm (don't send the signal)
#any true value will do, if this line is reached the or do below won't run
1;
} or do {
#if we are in this block something bad happened, so we need to find out
#what it was by looking at the $@ variable which holds the reason the
#the code above died
if ($@ eq "timeout\n") {
#if $@ is the timeout message then we timed out, take the
#proper clean up steps here
} else {
#we died for some other reason, possibly a syntax error or the code
#issued its own die. We should look at $@ more carefully and determine
#the right course of action. For the purposes of this example I will
#assume that a message of "resource not available\n" is being sent by
#the thing that takes a long time and it is safe to continue the program.
#Any other message is unexpected.
#since we didn't timeout, but the code died, alarm 0 was never called
#so we need to call it now to prevent the default ALRM signal handler
#from running when the timeout is up
alarm 0;
if ($@ eq "resource not available\n") {
warn $@;
} else {
die $@;
}
}
или написана более компактно:
eval {
local $SIG{ALRM} = sub { die "timeout\n" };
alarm $wait; #wait $wait seconds and then send the ALRM signal
#thing that could take a long time
alarm 0;
1;
} or do {
die $@ unless $@ eq "timeout\n" or $@ eq "resource not available\n";
alarm 0;
warn $@;
}