Re: Perl threads - telling them urgent stuff
by BrowserUk (Patriarch) on Oct 20, 2003 at 00:11 UTC
|
One method is to use a shared variable as a flag to indicate that the background thread shoudl die. This requires that yo arrange for the background thread to check the flag periodically.
Another (better) option, if your OS is *nix, would be to look at liz's Thread::Signal package.
If your OS is Win32, then you could look at using Win32::API to gain access to the native OS call, TerminateThread(). However, to use this you need to gain access to the native thread handle which the threads API does not provide accesss to. There is a native API GetCurrentThreadId(), which will return the handle, but this must be called from the thread that you want to kill. So, you would have to obtain the native thread handle at the start of the background thread and save it to a shared variable so that the foreground thread can access it when it is time to terminate the thread.
Note: This would kill the thread in mid-flow, which is crude and not very "structured". Having the backgound thread periodically check a flag and exit gracefully is a better idea.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
Hooray!
| [reply] |
|
|
According to the author of the original post, he has already considered shared variable, and he described the problem with that, so that's not what he asked for.
No, Thread::Signal is not a better option, and it is even not an option. this problem is more difficult than it sounds.
The problem described in the original post is not that he can not receive signal, on the contrary, he can receive signal with no problem. The same problem (the real problem) exists for both threads module and Thread::Signal module. What he really had problem with is how to instrcut the spider thread to stop. Assume he received a signal or anhthing similar, what he should do to stop the spider thread.
If you don't care whether the program stops decently, the thing becomes much easy. If Tk runs on main thread (most likely), just have a button, when the user clicks it, exit. For example:
use Tk;
use IO::Socket::INET;
use threads;
use strict;
use warnings;
$| ++;
threads->create(\&a);
my $mw = MainWindow->new(title => "window");
$mw->Button(text => "exit", command => sub {exit})->pack();
MainLoop;
sub a {
sleep(10000);
}
If he wants to quit, he can quit, just whether it is decent enough to the author's standard.
A real problem he might encounter is that the spider thread can take up lots of CPU cycles, and makes the Tk thread not responding. In that case, what he needs is make the spider thread yields (threads module delivers this) periodically, so the Tk thread get a chance to run. | [reply] [d/l] |
|
|
... what he needs is make the spider thread yields (threads module delivers this) periodically...
I think this is bad advice generally. My experience with yield() is that it just eats CPU, as it is a noop at least on some versions of Linux (I don't know about Windows, as I don't go there anymore).
Under Linux, each thread has its own pid (although it's pretty tricky to get it: this is basically the only XS functionality needed by Thread::Signal). So you are able to use POSIX::nice on that platform.
BrowserUK has been looking at setting priority of threads on Windows, but as he has described in several nodes in this thread, the problem is interfacing between what Perl thinks threads are and what the OS thinks threads are.
In a non-event driven situation, I would probably use a lock(), cond_wait() and cond_signal() combo by which threads tell each other something has happened or needs to be done. But obviously, that is a bit tricky doing from the Tk event loop.
Liz
| [reply] |
|
|
| [reply] |
|
|
|
|
|
Re: Perl threads - telling them urgent stuff
by pg (Canon) on Oct 19, 2003 at 23:36 UTC
|
Signal is per process, not per thread. this is not the fault of Perl, and is dictated by the system. | [reply] |
|
|
This is not true if you're running under Linux. Not sure whether that is by design of Perl, or by fluke. But it does allow my Thread::Signal to function.
Having said that, I would be in favor of either:
- expanding Thread::Signal to other platforms, using other message passing means.
- or, obsoleting Thread::Signal by another message passing means that would allow running on all platforms on which Perl can run with threads.
If anybody has any idea on how to go about doing this, let him/her come forward ;-)
Liz
| [reply] |
|
|
I realise that, what I'm looking for is something that works like signal but for threads instead of processes. In fact what I'm looking for is anything that would solve the above problem.
| [reply] |
Re: Perl threads - telling them urgent stuff
by Anonymous Monk on Oct 20, 2003 at 01:37 UTC
|
Thanks for all the suggestions, I'd like to quit gracefully if at all possible.
I guess I should have told you that this is a Win32 GUI (for a win32 version of my original version for *nix). So the Win32 response about terminating threads via the API is an interesting one.
However it's not just termination that's the problem. I was kind of hoping for a way of delivering immediate signals to the spider thread from the gui thread (like "Stop" or "Pause" and so on).
The only (kinda dodgy) solution I've come up with is to simply tell LWP (which I'm using to handle HTTP requests etc) to callback every 4kb and check if my flag is set. This seems to work a little better, but I guess this whole issue might count as an irritating problem with the current threads implementation, or I've just structured my code wrong from the beginning :). I don't know if threads under other APIs let you do this sort of thing, i'd be surprised if they didnt... | [reply] |
|
|
There are API's at the OS level that allow software interupts (Win32 equiv. of signals) between threads. Specifically, the native API QueueUserAPC().
Unfortunately, trying to get this to interoperate with Perls threads layer is frustratingly hard. I've been trying for some time, but the only way I can see to make this work is to patch the perl sources, and that is hard. Harder than I have been able to master.
I actually think your LWP callback method is anything but kludgy, and is probably they way I would approach the problem.
The alternative mught be to dump threads and look at POE. I should say that I know nothing about this, but I've seen merlyn recommend it several times now, so it might be worth your while looking at that.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
Hooray!
| [reply] |
|
|
POE looks interesting, and there's a Win32 version of it :) I've only scanned the docs but this might be a good way to go.
One thing I've noticed about perl ithreads is that they seem to take so *long* to initialise, at least on Win32, that threading little asynchronous functions whenever you need them can actually make the code run significantly slower :/ This is undoubtedly because perl copies the whole heap to the new thread, and I guess the performance problems with this is exactly why other threading APIs dont do it.
| [reply] |
|
|
Re: Perl threads - telling them urgent stuff
by BUU (Prior) on Oct 20, 2003 at 03:27 UTC
|
Perhaps I'm way off base, but you could just do something like
#in thread
$SIG{INT}=sub{ die; #etc}
#in tk/controller
`kill -1 $thread`
? Or is that signal stuff that was dismissed earlier and/or doesn't work on windows?
| [reply] [d/l] |