in reply to Detecting a port "in use" on localhost:$port

eval { local $SIG{ALRM} = sub { die "timeout" }; alarm($timeout); connect(SOCKET, $paddr) || error(); alarm(0); };

What is happening is (most likely) this:  when there's nothing listening on the port in question, the connect() fails more or less immediately ("connection refused") and the (non-existent) routine error() is being called. This dies with "Undefined subroutine &main::error called at...", so the alarm(0) isn't getting executed.  As the latter is supposed to reset the timer set up with the initial alarm($timeout), the timer keeps running and then fires later, outside of the eval{} scope, where the localized $SIG{ALRM} handler is no longer in effect...

In other words, the uncaught ALRM exception (on Windows emulated via SetTimer()/Windows Messages) is being reported as "Terminating on signal SIGALRM(14)".

Simplified demo:

#!perl eval { local $SIG{ALRM} = sub { die "timeout" }; alarm(1); error(); # not found -> dies alarm(0); }; print "\$@: $@\n" if $@; # do something that takes longer than a sec, # without itself being implemented via SetTimer() rand for 1..2e7; __END__ H:\PM>perl 759131.pl $@: Undefined subroutine &main::error called at 759131.pl line 6. Terminating on signal SIGALRM(14)

Solution:  either move the alarm(0) outside of the eval{} (so it's always being executed), or set $SIG{ALRM} ='IGNORE' outside of the eval{} to ignore the timer 'signal'.

Replies are listed 'Best First'.
Re^2: Detecting a port "in use" on localhost:$port
by freddo411 (Chaplain) on Apr 22, 2009 at 18:18 UTC
    Great explanation. I moved alarm(0) outside of eval and that seems to do the trick.

    thanks.

    -------------------------------------
    Nothing is too wonderful to be true
    -- Michael Faraday