sub worker {
exit 1;
}
my $thr = threads->create(\&worker);
while ($thr->is_running()) {
print "running\n";
}
my $rc = $thr->join();
exit $rc;
I come from Python. Is there something similar to try/except that I can use around while($thr->is_running)
I get (because I exit 1 in worker):
Perl exited with active threads:
0 running and unjoined
1 finished and unjoined
0 running and detached
I want to be able to catch the exit or other compiliation error worker might have
use strict;
use warnings;
use threads;
sub worker {
my $bad = 1/0;
}
my $thr = threads->create( \&worker );
while ( $thr->is_running() ) {
sleep 1;
}
my $rc = $thr->join(); #NB - RC will be 'undef' because there's no return.
OUTPUT:
Thread 1 terminated abnormally: Illegal division by zero at mythread.pl line 6.
Is it possible to catch it the error? and how and where?
Don't call exit in your thread. That exits your whole program. threads -> exit is what you want.
http://perldoc.perl.org/threads.html#EXITING-A-THREAD
threads->exit()
If needed, a thread can be exited at any time by calling threads->exit() . This will cause the thread to return undef in a scalar context, or the empty list in a list context.
When called from the main thread, this behaves the same as exit(0).
join waits for the thread to complete.
Don't use $a. It's a bad variable name anyway, but it's also used for perl sort.
You're capturing $rc but that implies a return in your thread. As it, it'll be undefined.
But this will work:
use strict;
use warnings;
use threads;
sub worker {
sleep 10;
threads->exit;
}
my $thr = threads->create( \&worker );
while ( $thr->is_running() ) {
print $thr ->tid, " running\n";
sleep 1;
}
print $thr ->tid, " not running\n";
sleep 5;
my $rc = $thr->join(); #NB - RC will be 'undef' because there's no return.
In the latter case, $rc is undef because you exited. You can test for it being undefined if you want to trap an abnormal exit. (Just make sure you do actually return something on a success).
Alternatively, wrap your code in the thread with an eval because that won't be a fatal error. Doesn't come up too often, but I'd suggest rather than trying to capture the broad spectrum of possible fatal errors, you're far better off just testing whether it completed successfully instead.
To answer your second question - something like this:
use strict;
use warnings;
use threads;
sub worker {
sleep 5;
my $fatal = 1 / 0;
return 1;
}
sub otherworker {
sleep 4;
eval { my $fatal = 1 / 0; };
if ($#) { return $# }
else { return "No error" }
}
my $thr = threads->create( \&worker );
my $thr2 = threads->create( \&otherworker );
while ( $thr->is_running() ) {
print $thr ->tid, " running\n";
sleep 1;
}
print $thr ->tid, " not running\n";
foreach my $thread ( threads->list ) {
my $return_code = $thread->join;
if ( not defined $return_code ) {
print $thread ->tid(), ": terminated abnormally\n";
}
else {
print $thread ->tid, ": exited with $return_code \n";
}
}
Related
The following is a simple code example I'm working on. It just starts a thread, wait 5 seconds, and then terminate it.
#!/usr/bin/perl
use strict;
use warnings;
use threads;
sub thread_sub
{
threads->create(sub
{
sleep 5; # HERE A WHILE ROUTINEs EMULATED BY SLEEP
threads->detach();
});
}
thread_sub();
exit;
But the result is:
# ./multithread.pl
Perl exited with active threads:
1 running and unjoined
0 finished and unjoined
0 running and detached
This because it runs the thread but after that exit without waiting.
So, how can I wait for thread to finish before exit? I know there is is_running, but I don't known how to implement it in my code. Obliviously the reported code is just an example to understand how to implement is_running. Thank you.
To wait for a thread to finish, one typically uses the following:
$thread->join();
To wait for all threads, one would therefore use the following:
$_->join() for threads->list();
Don't detach the thread if this is what you are going to do.
About detach...
If you had fire-and-forget threads, you could use
use threads;
use threads::shared;
my $thread_count :shared = 0;
sub thread_sub {
{ lock $thread_count; ++$thread_count; cond_signal($thread_count); }
my $thread = async {
sleep 5;
{ lock $thread_count; --$thread_count; cond_signal($thread_count); }
};
$thread->detach(); # Free the small thread object as soon as it completes.
}
thread_sub();
# When it's time to exit:
{ lock($thread_count); cond_wait($thread_count) while $thread_count != 0; }
But that doesn't gain you much over just joining the threads, which is far simpler.
use threads;
sub thread_sub {
async {
sleep 5;
};
}
thread_sub();
# Periodically:
$_->join() for threads->list(threads::joinable);
# When it's time to exit:
$_->join() for threads->list();
Finally, it's more common in practice to create a pool of threads and reuse them rather then creating threads on the fly because thread creation is expensive in Perl. In this situation, detaching makes even less sense.
use threads;
use Thread::Queue qw( ); # 3.01+
use constant NUM_WORKERS => 3;
sub process_job { sleep 5 }
my $q = Thread::Queue->new();
for (1..NUM_WORKERS) {
async {
while (my $job = $q->dequeue()) {
process_job($job);
}
};
}
$q->enqueue('some_job');
# When it's time to exit:
$q->end();
$_->join() for threads->list();
I haven't used it, but look into Thread::Pool.
By the way, async { ... } is just a cleaner way of saying threads->create(sub { ... }).
Why are you doing this? Detaching a thread means that you don't care about its return or fate; it will finish and exit or be killed as the program is about to exit.
If you want to wait for it don't detach but join.
As for the question of how to use is_running, you need a thread object
use warnings;
use strict;
use feature 'say';
use threads;
$| = 1;
sub thread_sub
{
my $thr = threads->create(sub
{
## threads->detach();
sleep 2; say "\tprocessing ..";
sleep 2; say "\tdone";
});
return $thr;
}
my $thr = thread_sub();
while ($thr->is_running) { # or: while (threads->list)
sleep 1;
say "main";
}
$_->join for threads->list; # instead of detaching
say "done";
Btw, a detached thread is also covered by is_running (or list) and the above works for it as well. But doing that doesn't make sense; I am just discussing the method you ask about.
Feeling stupid somehow as I'm now trying to get a simple interrupt for a thread working in groovy for some hours already.
Somehow following code won't set the 'interrupted' flag in the thread 'name'. Causing the loop to run 'til its end.
Found tons of other questions where usually the check for Thread.currentThread().isInterrupted() was missing. But this is not the case here:
def t = Thread.start('name') {
try {
for (int i = 0; i < 10 && !Thread.currentThread().isInterrupted(); ++i) {
println "$i"
sleep 1000
}
} catch (InterruptedException e) {
println "Catched exception"
Thread.currentThread().interrupt();
}
}
println "Interrupting thread in 1..."
sleep 1000
println "Interrupting thread..."
t.interrupt()
sleep 2000
I get following output
Interrupting thread in 1...
0
Interrupting thread...
1
2
3
4
5
6
7
8
9
Wonder what I miss here / am doing wrong?
Tried also using ExecutorService and calling cancel(true) on the returned Future. Didn't work either.
If you interrupt the thread while sleeping, the sleeping interrupted thread catches the InterruptedException thrown by Thread.sleep and the interrupted status is cleared. So your Thread.currentThread().isInterrupted() always returns false.
You can make your code work if you replace sleep 1000 with Thread.sleep(1000).
TL;DR: Do not use Thread interruption as abort criterion, but use some custom flag instead.
You are not using Thread.sleep() which would throw InterruptedException, but GDKs Object.sleep() which handles and ignores interruptions: http://docs.groovy-lang.org/docs/groovy-2.4.7/html/groovy-jdk/java/lang/Object.html#sleep(long)
Either use Thread.sleep() instead like: (interrupting in the catch block is useless in your case)
def t = Thread.start('name') {
try {
for (int i = 0; i < 10 && !Thread.interrupted(); ++i) {
println i
Thread.sleep 1000
}
} catch (InterruptedException e) {
println "Catched exception"
}
}
println "Interrupting thread in 1..."
sleep 1000
println "Interrupting thread..."
t.interrupt()
Or use the variant of Object.sleep() with a Closure and abort your loop in there, e. g. by throwing InterruptedException like:
def t
t = Thread.start('name') {
try {
for (int i = 0; i < 10 && !Thread.interrupted(); ++i) {
println i
sleep(1000) {
throw new InterruptedException()
}
}
} catch (InterruptedException e) {
println "Catched exception"
}
}
println "Interrupting thread in 1..."
sleep 1000
println "Interrupting thread..."
t.interrupt()
Having solved your confusion, now let me advice not to do what you are trying to do. Interrupting is any no way a good method for usage as abort condition. A sleep or blocking IO can always be interrupted due to various reasons. The much better approach is to make your run-loop check some boolean flag that you toggle to abort the work.
I was playing with this code, from the way the beep is sounding, once the program starts it doesn't stop. I suspect the problem is with $thread->kill('KILL')->detach;.
Any ideas? Or have I done something wrong ?
#!c:/perl/bin/perl
use threads;
use Audio::Beep;
my $thread;
my $playing=0;
while (1) {
my $val = int( rand(10) );
print "$val\n";
# if event "start" occurs and is not playing create thread
#if ( ($val==0 || $val==1 || $val==2 || $val==3 || $val==4 ) && (!$playing) ) {
if ( ($val==0 || $val==1 || $val==2 ) && (!$playing) ) {
$playing = 1;
$thread = threads->create(
sub {
local $SIG{'KILL'} = sub { threads->exit() };
print "start beep\n";
beep( 520, 10000 );
}
);
}
# if event "end" occurs and playing wait 1 seconf and kill thread
elsif ( ($val==5 ) && $playing ) {
print "stop beep \n";
#sleep(1);
$playing = 0;
$thread->kill('KILL')->detach;
}
#sleep(1);
$count = 0;
for($i=0; $i<99999 ; $i++) {
$count++;
}
}
I think your program is mostly working as you intend. One of the problems with what I see now is that every beep sounds alike. I re-wrote it a little to give the beep some texture, and to slow things down so that you can appreciate what's happening.
Also, as you've written it, there's a possibility that the thread will end on its own, before you can kill it. I've made the thread persistent, and added additional diagnostic information which will confirm when the thread is running and when it is not.
use strict;
use warnings;
use threads;
use Audio::Beep;
my $thread;
my $playing=0;
while (1) {
my $val = int( rand(30) );
print "$val\n";
my $running = threads->list(threads::running);
print "Threads running: $running\n";
# if event "start" occurs and is not playing create thread
if ( ( $val==1 ) && (!$playing) ) {
$playing = 1;
print ">>>>>>>>\n";
sleep(1);
$thread = threads->create(
sub {
local $SIG{'KILL'} = sub { threads->exit() };
print "start beep\n";
while (1) {
beep( 520, 100 );
sleep(1);
beep( 3800, 100 );
sleep(1);
beep( 2000, 100);
sleep(1);
}
}
);
}
# if event "end" occurs and playing wait 5 seconds and kill thread
elsif ( ($val==2 ) && $playing ) {
print "STOPSTOPSSTOPSTOPSTOP\n";
sleep(5);
$thread->kill('KILL')->detach;
$playing = 0;
}
for(my $i=0; $i<999999 ; $i++) {}
}
First of all, this is a follow up to a previous question of mine.
I would like to use threading in Tcl but in collaboration with Itcl.
Here is a sample:
package require Itcl
package require Thread
::itcl::class ThreadTest {
variable thread [thread::create {thread::wait}]
variable isRunning 0
method start {} {
set isRunning 1
thread::send $thread {
proc loop {} {
puts "thread running"
if { $isRunning } {
after 1000 loop
}
}
loop
}
}
method stop {} {
set isRunning 0
}
}
set t [ThreadTest \#auto]
$t start
vwait forever
However, when the condition statement tries to execute and check if the isRunning variable is true, I get a no such variable error. I understand that this is because a proc only has access to the global scope. However, in this situation, I would like to contain the variable local to the class.
Is there a way to accomplish this?
Tcl variables are per-interpreter, and interpreters are strongly bound to single threads (which greatly reduces the number of global-level locks required). To do what you want, you need to use a shared variable. Luckily, support for them is included with the Thread package (documentation here). You might then rewrite your code like this:
package require Itcl
package require Thread
::itcl::class ThreadTest {
variable thread [thread::create {thread::wait}]
constructor {} {
tsv::set isRunning $this 0
}
method start {} {
tsv::set isRunning $this 1
thread::send $thread {
proc loop {handle} {
puts "thread running"
if { [tsv::get isRunning $handle] } {
after 1000 loop $handle
}
}
}
thread::send $thread [list loop $this]
}
method stop {} {
tsv::set isRunning $this 0
}
}
set t [ThreadTest \#auto]
$t start
vwait forever
I am attempting to get a thread running which will be responsible for detecting a signal from any other thread within the same process.
sigset_t sigset;
sigfillset(&sigset);
pthread_sigmask( SIG_BLOCK, &sigset, &old );
Once i've done this, I then daemonize the process:
m_child = fork();
if (m_child == 0)
{
// Start the thread responsible for detecting a signal
}
This is done within another class called "SignalHandler" where the kick-off to this thread is done as follows:
m_pThread = new boost::thread( boost::bind(&SignalHandler::operator(), this ) );
and the functor operates in a tight loop as follows:
while (1)
{
if ( sigtimedwait( &sigset, &info, &ts ) == -1 )
{
if ( errno == EAGAIN || errno == EINTR )
{
std::cout << "Time-out waiting for signal" << std::endl;
}
throw SystemError( "sigtimedwait error" );
}
else
{
std::cout << "Detected a signal [" << info.si_signo << "]" << std::endl;
}
}
This works when I do a "kill -9 myProcess", but when I actually perform some illegal pointer manipulation (in any other thread), the process core dumps.
Why is the signal produced by the child thread not caught in my boost signal-catching thread?
Ah - I got it.
The problem is here:
sigset_t sigset;
sigfillset(&sigset);
pthread_sigmask( SIG_BLOCK, &sigset, &old );
Using sigfillset for pthread_sigmask is dangerous because blocking the synchronous signals causes undesirable effects.
If any of the SIGFPE, SIGILL, SIGSEGV,
or SIGBUS signals are generated while
they are blocked, the result is
undefined, unless the signal was
generated by the kill() function, the
sigqueue() function, or the raise()
function.