How to set timeout for a long running Sybase sp in Perl

柔情痞子 提交于 2019-12-08 04:37:40

问题


I'm calling a stored procedure which deletes data from Sybase DB in a Perl. But the sp takes hours to complete. I just want the sp to run for 1 hour, then no matter whether it completes or not I want the codes afterwards to be running. How can I implement this?

sub DelRef {
    print "starting defRefData\n";
    $db = new Sybapi($user, $password, $server, $margin_database); 
    #the following sql will take hours
    $db->exec_sql("exec CPN_Margins..clean_up_refData_db '$XrefCode'");
}

&DelRef();
print "process is done\n";
$db->close();

回答1:


I'm always wary of using alarm to interrupt a system call, as I find it hard to predict when the signal will be ignored or worse.

An alternative is to run your long-running code in a background process, and monitor its progress in the main process.

# DelRef() might take a while ...
my $start_time = time;
my $pid = fork();
if ($pid == 0) {
    # child process
    DelRef();
    exit 0;
}
# parent process
while (1) {
    use POSIX qw( WNOHANG );
    my $waitpid = waitpid $pid, WNOHANG;
    if ($pid == $waitpid) {
        print STDERR "DelRef() finished successfully\n";
        last;
    }
    if (time - $start_time > 3600) {
        print STDERR "DelRef() didn't finish in an hour\n";
        kill 'TERM',$pid;    # optional
        last;
    }
    print STDERR "DelRef() is still running ...\n";
    sleep 60;
}
print STDERR "... the rest of the script ...\n";



回答2:


You can use 'alarm' for this https://perldoc.perl.org/functions/alarm.html

    my $timeout = 3600; # 1hr = 3600 sec
    eval {
        local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
        alarm $timeout;
        $db = new Sybapi($user, $password, $server, $margin_database); 
        $db->exec_sql("exec CPN_Margins..clean_up_refData_db '$XrefCode'");
        alarm 0;
    };
    if ($@) {
        die unless $@ eq "alarm\n";   # propagate unexpected errors
        # timed out
    }
    else {
        # didn't timed out
    }

Also what is 'Sybapi'? In the past I have use 'DBD::Sybase' to connect to Sybase ASE(or 'sybperl' in old legacy code), and 'DBD::SQLAnywhere' to connect to Sybase IQ.



来源:https://stackoverflow.com/questions/58146492/how-to-set-timeout-for-a-long-running-sybase-sp-in-perl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!