Search code examples
perltimeoutsybase

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


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();

Solution

  • 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";