in reply to Re: Cannot catch ALRM signal for timeout
in thread Cannot catch ALRM signal for timeout

and then the system read is called to fill the buffer again...

You make it sound like Perl launches a thread to fill the buffer in the background. In reality, it's eof that reads from the file.

Move the eof into the eval and the timeout will take effect.

Replies are listed 'Best First'.
Re^3: Cannot catch ALRM signal for timeout
by almut (Canon) on Dec 08, 2009 at 15:57 UTC
    You make it sound like Perl launches a thread to fill the buffer

    That's not what I meant.  Perl tries to fill the buffer whenever it's empty and something is attempting to read from it — which in this case is the eof, as you note.

Re^3: Cannot catch ALRM signal for timeout
by Magice (Novice) on Dec 08, 2009 at 19:59 UTC
    ikegami, what do you mean by "move the eof into the eval"? I try this:
    sub process_scheme{ my ($output_file) = @_; open (OUTPUT_FILE, ">", $output_file) || die "cannot open lo +g file"; my $scheme_pid = open (WORKER, "worker_program < $input |") || die "cannot pipe worker"; my $str; while (1) { eval{ local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n r +equired alarm 1; if (eof(WORKER)){ close WORKER; close OUTPUT; return 1; } $str = <WORKER>; alarm 0; # if this line is removed, the signal is ca +ught, but outside of eval, so it halts the script }; if ($@) { close OUTPUT_FILE; close WORKER; return 0; } # process the line # some code ... # print the line to log print OUTPUT_FILE $str; } }
    but it still does not work :( Thank you for your hint, tho

      but it still does not work

      What doesn't work?

      The timeout works fine. I changed

      my $scheme_pid = open (WORKER, "worker_program < $input |")
      to
      my $scheme_pid = open (WORKER, "-|", $^X, '-e', '$|=1; for (1..100) { +print "%d\n", $_*$t; sleep(2) }')

      and the timeout triggered. The log file contained only "0".

      You'll need to fix the return 1, though. That will only return out of the eval, not out of the sub.

        It still stuck, not alarmed for some reasons. My code right now has become:
        sub process_scheme{ my ($output_file) = @_; open (OUTPUT_FILE, ">", $output_file) || die "cannot open log file +"; my $scheme_pid = open (SCHEME, "./t.pl | ") || die "cannot pipe sc +heme"; my $str = ""; MAIN: while (1) { eval{ local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n require +d alarm 5;#$allow_time; if (eof(SCHEME)){ close OUTPUT_FILE; close SCHEME; last MAIN; } $str = <SCHEME>; alarm 0; }; if ($@) { close OUTPUT_FILE; kill $scheme_pid; close SCHEME; return -$current_player; } # process the line print OUTPUT_FILE $str; } return 1; }
        where the t.pl is
        while(1){};
        The script gets stuck, waiting forever, not stopping/returning anything