A workaround would be to not use the blocking function of join. Something like this would work:
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
sub worker {
print "Worker thread started.\n";
while(1){}
}
my $thread = threads->create(\&worker);
print "Setting alarm.\n";
$SIG{ALRM} = sub { die "Alarm!\n" };
alarm 2;
print "Check join\n";
while (threads::running) {
$_->join for threads->list(threads::joinable);
}
Yes, I am aware that this will spin like crazy, wasting a lot of system resources, however you can't sleep to limit this, as sleep is sometimes implemented using the system alarm. Actually thinking about it some more, I suspect that join may have been modified to use the system alarm, hence wiping out the alarm you initially set, causing it to never trigger.
Based on this, a "better" approach could be something like this:
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
use constant TIMEOUT => 2;
sub worker {
print "Worker thread started.\n";
while(1){}
}
my $thread = threads->create(\&worker);
print "Check join\n";
while (1) {
$_->join for threads->list(threads::joinable);
last unless threads->list(threads::running);
die "Alarm!\n" if time - $^T > TIMEOUT;
select(undef,undef,undef,0.5);
}
Update: Updated second code example