Re: Perl5.8.4 , threads - Killing the "async" kid
by BrowserUk (Patriarch) on Oct 11, 2010 at 18:08 UTC
|
How can I ensure the main thread shuts down other threads before shutting itself down with exit.
If your only goal is to suppress the error messages, the simplest way is to use POSIX::_exit() from your main thread once it has done whatever clean-up and finalisations you require.
I don't advocate that as a general solution, but if there is no clean-up to be done in the threads, and you cannot move to a more modern version of Perl then it is the simplest.
If you are prepared to do a little more work, then use a threads::shared variable to tell your threads to finish. The complication comes because the simplicity of:
my $thread300 = async {
while( sleep 300 ) {
...
}
};
Has to become something like: my $timeToExit : shared = 0;
sub shutdown{
print logTime." INT|ABRT|QUIT|TERM received....shutting down servic
+e.\n";
$timeToExit = 1; ## Tell the threads to quit
sleep 1; ## give them time to react
close(LOOK_FOR_LEASE) if fileno(LOOK_FOR_LEASE);
close(OUTPUT) if fileno(OUTPUT);
close(ERROR) if fileno(ERROR);
threads->exit();
}
...
my $thread300 = async {
my $sleepTime = 300;
while( !$timeToExit ) {
sleep 1 and next while --$sleepTime;
$sleepTime = 300;
...
}
};
Now you can set $timeToExit = 1; in your main thread signal handler and know that the thread will terminate within one second. Not so complicated.
With later versions of threads there are the "signal handling" options, but in reality, they are no better than a simple shared variable. You still have to poll because the 'threaded-signals' (KILL etc.) don't interrupt anything.
However--and this is my recommendation--based on the pseudo-code you've posted which suggests the threads in question have no clean up to perform, nor any values to return, I would suggest upgrading to (the binary compatible) 5.8.9 and detaching the threads.
The warnings output in earlier versions about "still running detached thread" were recognised to be a design error, and were removed: c:\test> \perl32\bin\perl -Mthreads -e"print $]; async{ sleep 1000 }->
+detach; sleep 5"
5.008009
c:\test>
What that snippet shows, is that with 5.8.9, when the main thread's 5 second sleep times out, the detached thread is still running (but sleeping) and the program ends without any warning message. Detached threads are, by definition, fire-and-forget, so the earlier warnings were just wrong.
If you really can't upgrade, using POSIX::_exit()--once you've cleaned up everything that needs cleaning up--is a hackish way of achieving your stated goal.
A final thought is: these are only informational messages. You could simple document them as being "known and correct" and otherwise just ignore them!
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
Firstly,
thanks everyone and BrowserUK for the responses.
Below are my responses to select parts of the follow-ups.
1.BrowserUK wrote:
However--and this is my recommendation--based on the pseudo-code you've posted which suggests the threads in question have no clean up to perform, nor any values to return, I would suggest upgrading to (the binary compatible) 5.8.9 and detaching the threads.
Well, I am to blame here. The pseudo-code, as expected, did not reveal much.
This code below is declared before any thread is defined at the very top of the program. In effect, what I have done is to declare redirects for STDOUT and STDERR to a log file. And this is shared by all threads.
# Opening log file.
# Redirecting OUTPUT and ERR to log file for all threads
open OUTPUT, '>>', "/usr/local/xxx/log/lease.log" or die $!;
open ERROR, '>>', "/usr/local/xxx/log/lease.log" or die $!;
STDOUT->fdopen( \*OUTPUT, 'w' ) or die $!;
STDERR->fdopen( \*ERROR, 'w' ) or die $!;
This simplifies my logging process but it, in turn creates problems when I shut the daemon down. Please keep in mind the the signal handler itself is shared by all threads which means each process has it's signal handlers defined. So what I needed to write in the signal handler was a clean closing of threads and file-handles, independent of the active thread.
I thought about something similar to $timetoExit before posting here but did not know how to get beyond that point.
The
sleep 1 and next while --$sleepTime;
was what I was looking for. Saw it. Loved it. Tested it with a mild tweak. And no more error messages.
2.BrowserUK wrote:
Detached threads are, by definition, fire-and-forget, so the earlier warnings were just wrong.
I did try detaching the thread. But the error message kept coming. And I was also worried about the open file handles in the async thread. I kept imagining the main thread receiving a SIGTERM while the sync thread was trying to write to the file-handle. I believe this is a possibility.
| [reply] [d/l] [select] |
|
|
Please keep in mind the the signal handler itself is shared by all threads which means each process has it's signal handlers defined.
Hm. Does that mean that you are mixing threads and processes? Or are you just conflating the two terms? I'm going to assume the latter.
In a threaded process, if you install a signal handler using the 'normal mechanism' of %SIG, then that signal handler will only be called on the main thread. I assume--but haven't tested--this is the same for sigtrap.
I did try detaching the thread. But the error message kept coming.
It will unless you upgrade to a later version of perl. The warning about detached threads is no longer produced for 5.8.9. It may have been removed earlier, I don't recall, but if you were to upgrade, you might as well at least go as far as 5.8.9 and benefit from other fixes that came from that release also.
And I was also worried about the open file handles in the async thread. I kept imagining the main thread receiving a SIGTERM while the sync thread was trying to write to the file-handle. I believe this is a possibility.
If you are sharing these file handles between threads, then you should be synchronising access to them anyway. Ie. declare a shared variable for use as a mutex, take a lock() on them before printing to them and release it afterward.
Something like:
my $semSTDOUT :shared;
sub tprint{ lock $semSTDOUT; print @_; }
That's a very simplistic version, but demonstrates the point.
For the 'fire & forget' method, the signal handler would acquire a lock on that semaphore before exiting. That would ensure that none of your other threads could be in the process of writing to the handles when they are forcibly killed.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
|
Re: Perl5.8.4 , threads - Killing the "async" kid
by zentara (Cardinal) on Oct 11, 2010 at 17:07 UTC
|
HOW DO I KILL MY ASYNC BLOCK / LOGIN THREADS FROM HERE
On the old Perl versions, the spawned threads must reach the end of their code blocks, or return, before they can be joined. So, you must figure out a way to accomplish that. Otherwise, the warnings are harmless. Is there a way for you to signal the threads thru shared variables, to return?
| [reply] |
Re: Perl5.8.4 , threads - Killing the "async" kid
by locked_user sundialsvc4 (Abbot) on Oct 11, 2010 at 16:26 UTC
|
It appears to me that, as things stand now, you are calling exit() on the main thread, which shuts down the entire application, but you didn’t signal the child threads, nor did you wait for them to complete.
As shown in “thread signaling,” in the Threads documentation, you need to signal each thread to complete. Then, use join() to cause the main thread to wait-for and reap each one. Or, also as shown there, follow the KILL with an immediate detach(), although this seems less-than-elegant to me. I would run one loop that signals each thread (first...), then a second loop that reaps each thread.
Putting a tiny sleep() call just before the main-thread ends never hurts, either. An unnoticeable, but intentional, delay covers over a multitude of sins. (You know, the irritating little timing-holes that never show up in testing, but always appear when the CEO is looking at a big demo. I don’t like finger-dancing in such situations.)
| |
|
|
Hi
Perl 5.8.4 does not have features where you can send a kill signal from the main thread.
http://search.cpan.org/~nwclark/perl-5.8.4/pod/perlthrtut.pod
| [reply] |
|
|
| |
|
|
you can upgrade threads independent of perl
| [reply] |
|
|
|
|
|
|
| [reply] |
Re: Perl5.8.4 , threads - Killing the "async" kid
by locked_user sundialsvc4 (Abbot) on Oct 11, 2010 at 17:36 UTC
|
Why does "top" show me three process running even though no Login threads are running?
Depending on the thread-implementation that’s being used in your Perl and/or in your operating system, “threads” might appear as “processes.” For instance, the NPTL (New Posix Threads Library ... an operating-system feature) appeared in later versions of Linux but not earlier ones ...) As you may have guessed, I simply don’t know about details of the Threads packages in the earlier Perls.
| |
|
|
| [reply] |
|
|
I believe that the gist of the message (typo notwithstanding), and my general competence, is clearly understood by most. If it were not, I would not now have the rank that I have. If you have questions concerning either of these things, please take it up with me offline. If you find a posting to be significantly incorrect, please correct it. Or, call for a review by the priests.
| |
|
|