Thread

Posted on Wed Apr 4 15:35:38 2007 by calli
how to catch the SIG within detached threads
Hi, I wloud like (need) to catch the SIG{..} within detached theards.
I have seen the pool.pl example and saw, that this realized by a threaded var $TERM which is set by 'Mum', this means that $TERM has to be checked every wink in the threads.
But what if the detached threads were able and were set to sleep 1 hour before going on to work?
Despite that that there is nothing to do the loop has to keep on checking $TERM for the rare possibility that a SIG{..} was set.

Is there absolutely no possibilty that 'mum' send the the Signals received as well to her childs (or the childs cathes them themselves) causing the same effect within the childs like:
$SIG{USR1}='doSigUSR1';
$SIG{USR2}='doSigUSR2';
sub doSigUSR1 { .. }

and so on?
Direct Responses: 4755 | 4756 | Write a response
Posted on Wed Apr 4 15:52:05 2007 by calli in response to 4754
Re: how to catch the SIG within detached threads
the reason for what I need this, is just to enable the child to have a gracefull death, even if it were at sleep when SIG appears..
Write a response
Posted on Wed Apr 4 16:35:22 2007 by jdhedden in response to 4754
Re: how to catch the SIG within detached threads
As documented in the POD, the signals sent using $thr->kill() do not interrupt activities within the thread. If the thread is sleeping, it will only see the signal after the sleep call finishes, or if something interrupts the sleep call. As such, thread signalling is primarily useful for communication, and not that good for control.

However, you could use a regular signal to break the sleeps inside threads after you send them whatever signal you need:
#!/usr/bin/perl use strict; use warnings; $| = 1; use threads; # SIGINT is used to wake up threads $SIG{INT} = sub { print("Ignoring SIGINT\n"); }; sub thr1 { my $term = 0; $SIG{USR1} = sub { print("\tthr1 caught SIGUSR1\n"); $term = 1; }; while (! $term) { print("\tthr1 sleeping...\n"); sleep 100; print("\tthr1 woke up\n"); } print("\tthr1 done\n"); } sub thr2 { my $term = 0; $SIG{USR1} = sub { print("\t\tthr2 caught SIGUSR1\n"); $term = 1; }; while (! $term) { print("\t\tthr2 sleeping...\n"); sleep 100; print("\t\tthr2 woke up\n"); } print("\t\tthr2 done\n"); } MAIN: { print("Starting threads...\n"); my $thr1 = threads->create('thr1'); my $thr2 = threads->create('thr2'); $thr1->detach(); $thr2->detach(); sleep(1); print("\nSignalling thr1...\n"); $thr1->kill('USR1'); sleep(1); print("Waking up threads...\n"); kill('INT', $$); sleep(1); print("\nSignalling thr2...\n"); $thr2->kill('USR1'); sleep(1); print("Waking up threads...\n"); kill('INT', $$); sleep(2); } print("\nDone\n"); exit(0);
This produces:
Starting threads... thr1 sleeping... thr2 sleeping... Signalling thr1... Waking up threads... thr2 woke up thr2 sleeping... thr1 caught SIGUSR1 thr1 woke up Ignoring SIGINT thr1 done Signalling thr2... Waking up threads... thr2 caught SIGUSR1 Ignoring SIGINT thr2 woke up thr2 done Done
You'll have to try this yourself as there may be system dependency issues with signals.
Direct Responses: 4759 | 4767 | Write a response
Posted on Wed Apr 4 17:42:39 2007 by calli in response to 4756
Re: how to catch the SIG within detached threads
jdhedden,
thanks a lot for your immediate reply!!
I'll try tomorrow..
Carl
Write a response
Posted on Thu Apr 5 13:09:59 2007 by calli in response to 4756
Re: how to catch the SIG within detached threads
Well,
your program works, but if I change it that way,
that SIGs from 'outside' should force the thread-sleep to break
--- this fails:
#!/usr/bin/perl use strict; use warnings; $| = 1; use threads; our ($thr1,$thr2); sub thr1 { my $term = 0; $SIG{USR1} = sub { print("\tthr1 caught SIGUSR1\n"); $term = 1; }; while (! $term) { print("\tthr1 sleeping...\n"); sleep 100; print("\tthr1 woke up\n"); } print("\tthr1 done\n"); } sub thr2 { my $term = 0; $SIG{USR1} = sub { print("\t\tthr2 caught SIGUSR1\n"); $term = 1; }; while (! $term) { print("\t\tthr2 sleeping...\n"); sleep 100; print("\t\tthr2 woke up\n"); } print("\t\tthr2 done\n"); } $SIG{INT} = sub { print("Ignoring SIGINT\n"); print("\nSignalling thr1...\n"); $thr1->kill('USR1'); sleep(1); print("\nSignalling thr2...\n"); $thr2->kill('USR1'); sleep(1); print("Waking up threads...\n"); $SIG{INT} = 'DEFAULT'; kill('INT', $$); sleep(2); }; MAIN: { print("$$: Starting threads...\n"); $thr1 = threads->create('thr1'); $thr2 = threads->create('thr2'); $thr1->detach(); $thr2->detach(); while ( 1 ) { sleep 1; } } # SIGINT is used to wake up threads print("\nDone\n"); exit(0);
This produces after I typed kill -INT 8701:
8701: Starting threads... thr1 sleeping... thr2 sleeping... Ignoring SIGINT Signalling thr1... Signalling thr2... Waking up threads...

Now all, Mum and her 2 threads are dead, the threads died without a sigh :(
Carl
Direct Responses: 4768 | Write a response
Posted on Thu Apr 5 14:37:17 2007 by jdhedden in response to 4767
Re: how to catch the SIG within detached threads
The trouble with your example is that the default for SIGINT is to terminate the program. You need to catch and ignore whatever signal you use to wake up the threads.

In the code below, SIGTERM is caught from the outside (so that 'kill PID' can be used). It then uses SIGUSR2 to wake up the threads.
#!/usr/bin/perl use strict; use warnings; $| = 1; use threads; my ($thr1, $thr2, $term); # SIGUSR2 is used to wake up threads $SIG{USR2} = sub { print("Ignoring SIGUSR2\n"); }; $SIG{TERM} = sub { print("Caught SIGTERM\n"); # Send signals to threads print("Signalling thr1...\n"); $thr1->kill('USR1'); print("Signalling thr2...\n"); $thr2->kill('USR1'); print("Waking up threads using SIGUSR2...\n\n"); kill('USR2', $$); $term = 1; }; sub thr1 { my $term = 0; $SIG{USR1} = sub { print("\tthr1 caught SIGUSR1\n"); $term = 1; }; while (! $term) { print("\tthr1 sleeping...\n"); sleep 100; print("\tthr1 woke up\n"); } print("\tthr1 done\n"); } sub thr2 { my $term = 0; $SIG{USR1} = sub { print("\t\tthr2 caught SIGUSR1\n"); $term = 1; }; while (! $term) { print("\t\tthr2 sleeping...\n"); sleep 100; print("\t\tthr2 woke up\n"); } print("\t\tthr2 done\n"); } MAIN: { print("Starting threads...\n"); $thr1 = threads->create('thr1'); $thr2 = threads->create('thr2'); $thr1->detach(); $thr2->detach(); sleep(1); # Tell user what to do print("\nWaiting for termination signals: kill $$\n\n"); # Wait for termination signal while (! $term) { sleep(1); } # Give threads a chance to finish sleep(2); } print("\nDone\n"); exit(0);
You get output like:
Starting threads... thr1 sleeping... thr2 sleeping... Waiting for termination signals: kill 21892 thr1 woke up thr2 woke up thr1 sleeping... thr2 sleeping... Caught SIGTERM Signalling thr1... Signalling thr2... Waking up threads using SIGUSR2... thr1 caught SIGUSR1 thr2 caught SIGUSR1 Ignoring SIGUSR2 thr1 woke up thr2 woke up thr1 done thr2 done Done
At any rate, you should be getting the idea by now. You'll just have to work with the details to get exactly what you need done.
Direct Responses: 4770 | Write a response
Posted on Thu Apr 5 17:15:17 2007 by calli in response to 4768
Re: how to catch the SIG within detached threads
Sorry,
but I can't reproduce your printout
this is what I get - both threads die without any chance to sigh:
cas@Soltek:~/Perl/Bash> ./testSig3.pl Starting threads... thr1 sleeping... thr2 sleeping... Waiting for termination signals: kill 10029 Caught SIGTERM Signalling thr1... Signalling thr2... Waking up threads using SIGUSR2... Ignoring SIGUSR2 Done cas@Soltek:~/Perl/Bash>
I am running SuSE 9.3 and Perl 5.8.6 - could that be the reason?
Direct Responses: 4771 | Write a response
Posted on Thu Apr 5 17:33:02 2007 by jdhedden in response to 4770
Re: how to catch the SIG within detached threads
Then this is an issue with SuSE - the kill(USR2, ...) call is not knocking the threads off their sleep calls. You could try using INT instead of USR2. If that doesn't work, then you may not be able to do what you're hoping for. Good luck.
Write a response