Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
am I missing something?

Yes. I did not write about the system function, but about the system (as in "operating system"). I cited alarm in perlport: "Emulated using timers that must be explicitly polled whenever Perl wants to dispatch "safe signals" and therefore cannot interrupt blocking system calls. (Win32)" (Emphasis mine) I wrote " Replace sleep with something that blocks for 5 seconds outside perl (i.e. in the system) and alarm will no longer work."

Demo, using flock, a function using a system call that may block for a long time:

#!/usr/bin/perl use strict; use warnings; use v5.10; use Fcntl qw( LOCK_EX LOCK_UN ); use autodie qw( open flock close ); sub main { # create a tempfile open my $h,'>>','tempfile.tmp'; close $h; # start a background process that locks the tempfile for 10 second +s if ($^O eq 'MSWin32') { system 1,$^X,$0,'locker'; } else { my $pid=fork() // die "Can't fork: $!"; unless ($pid) { exec $^X,$0,'locker' or die "Can't exec: $!"; } } sleep 1; # wait one second for the helper process; open $h,'>>','tempfile.tmp'; $@=''; my $start=time(); eval { local $SIG{'ALRM'}=sub { die "timeout" }; say 'main: alarm 5'; alarm(5); say 'main: flock LOCK_EX'; flock($h,LOCK_EX); say 'main: alarm 0'; alarm(0); }; my $err=$@ || 'successfully locked'; my $stop=time(); say "main: $err"; say 'main: ',$stop-$start,' seconds have passed'; close $h; # allow locker() to finish before returning to command prompt ($^O eq 'MSWin32') ? sleep 1 : wait; } sub locker { open my $h,'>>','tempfile.tmp'; say 'locker: flock LOCK_EX'; flock($h,LOCK_EX); say 'locker: locked'; say 'locker: sleep 10'; sleep 10; say 'locker: flock LOCK_UN'; flock($h,LOCK_UN); say 'locker: unlocked'; close $h; } @ARGV ? locker() : main();

How the demo works:

Without arguments, main() is invoked, main() creates a background process (using system(1,@args) on Windows, fork() and exec() on Linux), waits a second, then tries to lock a temp file with a classic timeout construct (eval, $SIG{'ALRM'}=sub { die }, alarm($timeout), system call, alarm(0)). Time for this is measured. The background process is the same script, but invoked with an argument, so that locker() is invoked instead of main(). Locker locks the temp file for 10 seconds, and because main() waits a second, it will succeed. In main(), the temp file is already locked, so flock() will block until locker() releases the lock OR the system call is interrupted by the ALRM signal caused by alarm().

On Linux, signals just work. flock() in main() is interrupted by the ARLM signal, the signal handler in $SIG{'ALRM'} is invoked, that terminales the eval block using die() after 5 seconds.

On Windows, signals are emulated. alarm($timeout) sets up a timer that must be polled. This is impossible during a blocking system call like flock(). So flock() blocks until it can aquire the lock after about 9 seconds (locker() waits 10 seconds after locking, main() waits 1 second before trying to lock, 9 seconds remain). $SIG{'ALRM'} is not invoked. alarm(0) disables the timer. The eval block terminates without an error.

Output on Linux:

>perl locker: flock LOCK_EX locker: locked locker: sleep 10 main: alarm 5 main: flock LOCK_EX main: timeout at line 30. main: 5 seconds have passed locker: flock LOCK_UN locker: unlocked >

Output on Windows:

H:\tmp>perl locker: flock LOCK_EX locker: locked locker: sleep 10 main: alarm 5 main: flock LOCK_EX locker: flock LOCK_UN main: alarm 0 main: successfully locked main: 10 seconds have passed locker: unlocked H:\tmp>

So why did alarm($timeout) "work" with system "sleep 10"?

system @args (unlike system 1,@args) waits for the sub-process to terminate in perl. (flock() waits in the operating system!) During that time, perl can poll the timer and thus can emulate the ARLM signal.


Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

In reply to Re^3: Strawberry Perl and alarm() on Windows by afoken
in thread Strawberry Perl and alarm() on Windows by bloonix

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (2)
As of 2022-05-25 01:16 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (84 votes). Check out past polls.