Как я могу ограничить время, проведенное в определенном разделе сценария Perl?

Закройте любые открытые проекты, которые не находятся в текущем употреблении.

Попытка выключить автоматическое публикуют режим во время разработки.

7
задан YoDar 23 July 2009 в 08:28
поделиться

3 ответа

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

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.";
}
5
ответ дан 6 December 2019 в 09:21
поделиться

Вы можете установить сигнал тревоги, который сработает в вашем коде через указанное количество секунд:

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;
};
12
ответ дан 6 December 2019 в 09:21
поделиться

В 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 $@;
}
3
ответ дан 6 December 2019 в 09:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: