Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Timeout thread while it is in a system command

167 views
Skip to first unread message

Kasper Middelboe Petersen

unread,
May 9, 2012, 9:37:21 AM5/9/12
to
Hello,

I have a seemingly simple problem. I need to execute a series of
system commands (using `<cmd>`) in parallel.

The code below has been stripped of anything meaningful besides
demonstrating my problem:

#!/usr/bin/perl -w

use strict;
use threads;
use POSIX;

my @threads = ();

sub timeout {
print "TIMEOUT\n";
foreach my $thread (@threads) {
$thread->kill("ALRM") if $thread->is_running();
}
}
POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&timeout));

alarm(2);

sub threadsub {
sub handletimeout {
print "KILL\n";
threads->exit(1);
}
POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&handletimeout));

# while(1) { sleep(1); }
return `sleep 10`;
}

for(my $i=0; $i < 10; $i++) {
push(@threads, thread->create(\&threadsub));
}

foreach my $thread (@threads) {
my $res = $thread->join();
}


Now, the problem is the ALRM signal sent to the threads are never
caught when the thread is blocked in the system call. If you uncomment
the while loop the signal are caught as intended.

How do I make this work so I'm able to timeout my threads even if
they're stuck in the system command?

Thanks,
Kasper

Rainer Weikusat

unread,
May 15, 2012, 7:08:51 AM5/15/12
to
Kasper Middelboe Petersen <fant...@gmail.com> writes:
> I have a seemingly simple problem. I need to execute a series of
> system commands (using `<cmd>`) in parallel.
>
> The code below has been stripped of anything meaningful besides
> demonstrating my problem:
>
> #!/usr/bin/perl -w
>
> use strict;
> use threads;
> use POSIX;

[...]

> POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&timeout));
>
> alarm(2);
>
> sub threadsub {
> sub handletimeout {
> print "KILL\n";
> threads->exit(1);
> }
> POSIX::sigaction(SIGALRM, POSIX::SigAction->new(\&handletimeout));
>
> # while(1) { sleep(1); }
> return `sleep 10`;
> }

[...]

> Now, the problem is the ALRM signal sent to the threads are never
> caught when the thread is blocked in the system call. If you uncomment
> the while loop the signal are caught as intended.
>
> How do I make this work so I'm able to timeout my threads even if
> they're stuck in the system command?

SIGALRM is a so-called asynchronous signal and this means that it may
be handled by any thread not currently blocking it, IOW, this can't
work: There will be one SIGALRM generated for the process once the
alarm expires, no matter how many threads were started and this will
interrupt one (arbitrarily selected) thread (your signal handler is
also not 'safe', meaning, should be process be doing something more
complicated than executing an inifinite loop or being blocked in a
system call, all kinds of weird things can result).
0 new messages