Hey Steve,

I started to write you a message asking for a different strace, when I
noticed that you are passing attributes for set_sig_handler that
Sys::SigAction has no knowledge of:

  my $h = set_sig_handler('ALRM',sub {die "timeout";}, { trap => ['ALRM', 'INT' 
], safe=>0 });

The "trap" key in the hashref: { trap => ['ALRM', 'INT' ], safe=>0 } is
not used by Sys::SigAction.

This reference is passed from set_sig_handler() (line 91) to
mk_sig_action() (defined on line 94) where the 'flags' and the 'mask'
keys are referenced (lines 98 and 99). 

Sys::SigAction does not know anything about the key 'trap'.  And i don't
know how masking ALRM or INT can help you, and flags is used for setting
sigaction flags usually in the form of SA_flag that are passed to
sigaction() by perl.

Could you explain or fix this code, and then try again?

Lincoln
Author of Sys::SigAction

On Tue, 2009-02-24 at 15:37 +0000, Steve Freegard wrote:
> Hi,
> 
> I've been trying to implement a timeout wrapper for my database
> functions to handle a database connection that is remote and therefore
> could either become very slow of the link could disappear completely.
> 
> I'm using something like this:
> 
> use DBI;
> use Sys::SigAction;
> 
> my($dbh);
> eval {
>  my $h = set_sig_handler('ALRM',sub {die "timeout";}, { trap => [
> 'ALRM', 'INT' ], safe=>0 });
>  alarm(30);
>  $dbh = DBI->connect_cached(...);
>  alarm(0);
> };
> alarm(0);
> if($@) {
>  ...
> }
> 
> This works fine if the connection to the database is not already
> established and times out after 30 seconds correctly;  however if the
> database connection was established previously (and cached) it takes >
> 200 seconds to return instead of the expected 30 seconds.
> 
> An strace shows the following:
> 
> rt_sigaction(SIGALRM, NULL, {SIG_DFL}, 8) = 0
> rt_sigprocmask(SIG_BLOCK, [ALRM], ~[KILL STOP RTMIN RT_1], 8) = 0
> rt_sigaction(SIGALRM, {0xd30835, [], SA_RESTORER, 0xc29a98}, {SIG_DFL},
> 8) = 0
> rt_sigprocmask(SIG_SETMASK, ~[KILL STOP RTMIN RT_1], NULL, 8) = 0
> rt_sigaction(SIGALRM, {0xd3419d, [ALRM], SA_RESTORER, 0xc29a98}, NULL,
> 8) = 0
> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
> alarm(30)                               = 0
> rt_sigaction(SIGPIPE, {SIG_IGN}, {SIG_DFL}, 8) = 0
> send(6, "Q\0\0\0\37SELECT \'DBD::Pg ping test\'\0", 32, 0) = 32
> rt_sigaction(SIGPIPE, {SIG_DFL}, {SIG_IGN}, 8) = 0
> poll(
> [{fd=6, events=POLLIN|POLLERR}], 1, -1) = -1 EINTR (Interrupted system call)
> --- SIGALRM (Alarm clock) @ 0 (0) ---
> rt_sigprocmask(SIG_UNBLOCK, [ALRM], NULL, 8) = 0
> socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 9
> setsockopt(9, SOL_TCP, TCP_NODELAY, [1], 4) = 0
> fcntl64(9, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
> fcntl64(9, F_SETFD, FD_CLOEXEC)         = 0
> connect(9, {sa_family=AF_INET, sin_port=htons(5432),
> sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in
> progress)
> poll(
> *** hangs here for ~280 seconds ***
> 
> Does anyone have any idea as to what I'm doing wrong or how to
> workaround this??
> 
> Kind regards,
> Steve.
> 

Reply via email to