I am trying to execute one procedure on an auxiliary thread while the rest of my code will be executed in parallel. I have this small example:
set thread_loadmaterials [thread::create]
thread::send -async $thread_loadmaterials [list wa "hola from thread_loadmaterials"]
thread::send -async [thread::id] [list wa "hola from thread::id"]
NOTE: The created thread, checked by thread::exists procedure, exists.
The thread_loadmaterials has the created thread id and it's a different id than the active
thread ([thread::id]).
To my surprise, the thread identified by [thread::id] is showing the message but the thread that I create, don't do anything.
If someone can help me to understand it, I will be a lot grateful.
The man page on thread::send -async says:
The target thread must enter it's event loop in order to receive
scripts sent via this command. [...] Threads can enter the event loop
explicitly by calling thread::wait or any other relevant Tcl/Tk
command, like update, vwait,
You never have the main thread (as identified by thread::id) in your script enter the event loop, e.g., by calling vwait
That said, there is no real need of thread::send'ing to the self, and here main thread.
Related
I have a small sample program that hangs on perl 5.16.3. I am attempting to use an alarm to trigger if two threads don't finish working in time in a much more complicated program, but this boils down the gist of it. I know there's plenty of other ways to do this, but for the sake of argument, let's say I'm stuck with the code the way it is. I'm not sure if this is a bug in perl, or something that legitimately shouldn't work.
I have researched this on the Internet, and it seems like mixing alarms and threads is generally discouraged, but I've seen plenty of examples where people claim that this is a perfectly reasonable thing to do, such as this other SO question, Perl threads with alarm. The code provided in the accepted answer on that question also hangs on my system, which is why I'm wondering if maybe this is something that's now broke, at least as of 5.16.3.
It appears that in the code below, if I call join before the alarm goes off, the alarm never triggers. If I replace the join with while(1){} and go into a busy-wait loop, then the alarm goes off just fine, so it appears that join is blocking the SIGALRM for some reason.
My expectation is that the join happens, and then a few seconds later I see "Alarm!" printed on the screen, but this never happens, so long as that join gets called before the alarm goes off.
#!/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 { print "Alarm!\n" };
alarm 2;
print "Joining.\n";
$thread->join();
The problem has nothing to do with threads. Signals are only processed between Perl ops, and join is written in C, so the signal will only be handled when join returns. The following demonstrates this:
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
sub worker {
print "Worker thread started.\n";
for (1..5) {
sleep(1);
print(".\n");
}
}
my $thread = threads->create(\&worker);
print "Setting alarm.\n";
$SIG{ALRM} = sub { print "Alarm!\n" };
alarm 2;
print "Joining.\n";
$thread->join();
Output:
Setting alarm.
Joining.
Worker thread started.
.
.
.
.
.
Alarm!
join is essentially a call to pthread_join. Unlike other blocking system calls, pthread_join does not get interrupted by signals.
By the way, I renamed $tid to $thread since threads->create returns a thread object, not a thread id.
I'm going to post an answer to my own question to add some detail to ikegami's response above, and summarize our conversation, which should save future visitors from having to read through the huge comment trail it collected.
After discussing things with ikegami, I went and did some more reading on perl signals, consulted some other perl experts, and discovered the exact reason why join isn't being "interrupted" by the interpreter. As ikegami said, signals only get delivered in between perl operations. In perl, this is called Deferred Signals, or Safe Signals.
Deferred Signals were released in 5.8.0, back in 2002, which could be one of the reasons I was seeing older posts on the Net which don't appear to work. They probably worked with "unsafe signals", which act more like signal delivery that we're used to in C. In fact, as of 5.8.1, you can turn off deferred signal delivery by setting the environment variable PERL_SIGNALS=unsafe before executing your script. When I do this, the threads::join call is indeed interrupted as I was expecting, just as pthread_join is interrupted in C in this same scenario.
Unlike other I/O operations, like read, which returns EINTR when a signal interrupts it, threads::join doesn't do this. Under the hood it's a call to the C library call pthread_join, which the man page confirms does not return EINTR. Under deferred signals, when the interpreter gets the SIGALRM, it schedules delivery of the signal, deferring it, until the threads::join->pthread_join library call returns. Since pthread_join doesn't "interrupt" and return EINTR, my SIGALRM is effectively being swallowed by the threads::join. With other I/O operations, they would "interrupt" and return EINTR, giving the perl interpreter a chance to deliver the signal and then restart the system call via SA_RESTART.
Obviously, running in unsafe signals mode is probably a Bad Thing, so as an alternative, according to perlipc, you can use the POSIX module to install a signal handler directly via sigaction. This then makes the one particular signal "unsafe".
I found a piece of strange code in a open source software
for (i=0; i<store->scan_threads; i++) {
pthread_join(thread_ids[i], NULL);
pthread_detach(thread_ids[i]);
}
Is there any meaning to call pthread_detach ?
That stanza is silly and unsafe.
Design-wise, the detach is unnecessary — the join completion already means that the thread is completely finished. There's nothing to detach. (The code in question simply spawns threads with default joinability.)
Implementation-wise, the detach is unsafe. A thread ID may be recycled as soon as the thread is finished — oops, didn't mean to detach that other thread! Worse, the ID is not guaranteed to be meaningful at all after the call to join returns — SEGV?
In this code (considering that this code is from main thread.... )
pthread_join(thread_ids[i], NULL);
this will wait the main thread to return thread with thread id "thread_ids[i]", and if main thread is doing some more work then
pthread_detach(thread_ids[i]);
will release the resource used by the thread (with thread id "thread_ids[i]).
I have a form that is responsible for creating and setting up an instance of an object, and then telling the object to go do its work. The process is a long one, so there's an area on the form where status messages appears to let the user know something is happening. Messages are set with a setMessage(string msg) function. To allow the form to remain responsive to events, I create a new thread for the object to run in, and pass it the setMessage function as a delegate to allow the object to set status messages on the form. This part is working properly. The main form is responsive and messages posted to its setMessage function appear as expected.
Because the process is a long one, and is made up of many steps, I want to allow the user to terminate the process before it's finished. To do this I created a volatile bool called _stopRequested and a function called shouldStop() that returns its value. This is also given to the object as a delegate. The object can tell if it should terminate by checking shouldStop() periodically, and if it's true, shut down gracefully.
Lastly, Windows controls are not thread safe, so the compiler will complain if a thread other than the one that created the control tries to manipulate it. Therefore, the setMessage function is wrapped in an if statement that tests for this and invokes the function using the parent thread if it's being called from the worker thread (see http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx for a description).
The problem arises when the user requests a shutdown. The main form sets _stopRequested to true and then waits for the child thread to finish before closing the application. It does this by executing _child.Join(). Now the parent thread (the one running the form) is in a Join state and can't do anything. The child thread (running the long process) detects the stop flag and attempts to shut down, but before it does, it posts a status message by calling it's setMessage delegate. That delegate points back to the main form, which figures out that the thread setting the message (child) is different than the thread that created the control (parent) and invokes the function in the parent thread. The parent thread is, of course, in a Join state and won't set the text on the text box until the child thread terminates. The child thread won't terminate because it's waiting for the delegate it called to return. Instant deadlock.
I've found examples of signaling a thread to terminate, and I've found examples of child threads sending messages to the parent thread, but I can't find any examples of both things happening at the same time. Can someone give me some pointers on how to avoid this deadlock? Specifically, I'd like the form to wait until the child thread terminates before closing the application but remain able to do work while it waits.
Thanks in advance for the advice.
1-(lazy) Dispatch the method from a new Thread so it doesn't lock
2-(re-think) The main UI thread should be able to control the child thread, so forget the _stopRequested and shouldStop() and implement a childThread.Abort() , abort does not kill the thread, but sends a ThreadAbortException
which can be handled or even canceled
catch(ThreadAbortException e)
{
ReleaseResources();
}
Make the ReleaseResources safe by making various checks such as:
resource != null
or
resource.IsClosed()
The ReleaseResources should be called normally without abort and also by abort.
3-(if possible)stop the child, via main thread call ReleaseResources()
You may have to implement a mix of these.
I have a system with multiple I/O interfaces, and I'm collecting the output of all of them into a common log. Two of the interfaces are through well-behaved channels that are opened as file-like objects, and can be managed on an event basis with "fileevent readable". The other two are the problem.
These are to a vendor-supplied library, which someone else has already kindly wrapped into a Tcl package (snoopy, FWIW). However, the only read access is a blocking call, and there's nothing in the package that would cause an event equivalent to a fileevent.
I've figured out how to spawn a separate thread to block on the read, pull the result, and put it into a message queue for the main thread. But having the main thread block on reading the queue would seem to defeat the purpose, especially since there are two queues it would have to block on. And I haven't been able to get the reader to generate an event that can trigger the main thread to read the queue.
I've looked on the tcl.tk wiki to no avail so far. I've tried using the uevent library to generate an event on a message push, but the event goes to the writing thread instead of the reading thread, which really doesn't help. It seems like there should be some solution related to a Thread condition variable, but so far I haven't been able to find an appropriate design pattern for that use of the library.
If all else fails I'll fall back to a Tk event, but I'm trying to keep Tk out of this as it's meant to be an automated system with no GUI, and any mention of Tk pushes tclsh into wish and pops up a GUI window.
I feel like I'm close, but just missing something.
Firstly, the main thread needs to run the event loop in order to receive events. The idiomatic way to do this is to use vwait forever once you've finished setting up your program (I assume you're not going to write to that variable) but if you are running Tk you already have an event loop (GUIs need event loops).
There are two ways to do the messaging between threads.
Thread events
The thread::send command uses events to dispatch code to execute (the message) between threads. All you need to do is to tell the worker thread what the main thread's ID is so it knows where to send to. Note that you may well want to send the event asynchronously, like this:
thread::send -async $mainID [list eventReceiver "something happened" $payload]
Pipelines
If you're using Tcl 8.6, you can use chan pipe to create an unnamed OS pipeline. You can then use normal fileevents, etc., to deliver information from thread to another that way.
# In master
lassign [chan pipe] readSide writeSide
thread::transfer $worker $readSide
thread::send $worker [list variable pipe $readSide]
fconfigure $writeSide -blocking 0
fileevent $writeSide readable [list handleLine $writeSide]
# In worker
fconfigure $pipe -blocking 0 -buffering line
puts $pipe "got event: $payload"
It's probably easier to use thread events in retrospect! (The main advantage of a pipe is that you can also put the worker in another process if necessary.)
I finally grokked what Donal was saying about Thread events. I blame inadequate morning caffeine for not getting it the first time.
All the prior examples of thread::send I've seen concerned a master sending scripts down to the worker thread. In this case, the worker thread needs to send scripts back up to the master, where the script is the one that would be called on [fileevent readable] if this was a channel.
Here's my test code for the interaction:
proc reader {payload} {
puts $payload
}
set t1 [thread::create]
thread::send -async $t1 {
proc produce {parentid} {
while 1 {
after 250 ;# substitutes for
incr data ;# the blocking read
thread::send $parentid "reader $data"
}
}
}
set tid [thread::id]
thread::send -async $t1 [list produce $tid]
vwait forever
The part I saw but didn't immediately grok was the importance of the master thread having an ID that can be sent to the worker. The key that I'd missed was that the worker can send scripts to the master just as easily as the master can send scripts to the worker; the worker just usually doesn't know the master's Thread ID.
Once the ID is passed to it, the producer thread can therefore use thread::send to call a proc in the master to handle the data, and it becomes an event in the master thread, just as I'd desired. It's not the way I've worked with threads in the past, but once understood it's powerful.
if a threadA is sleeping, how will another thread threadB call threadA to start ?
Please provide an example if possible.
Instead of sleeping you will want to create an EventWaitHandle and use WaitOne with a timeout.
When you want the thread to wake-up early, you will simply set the event to signaled.
First create the EventWaitHandle:
wakeUpEvent = new EventWaitHandle(false, EventResetMode.ManualReset);
Then in your thread:
wakeUpEvent.WaitOne(new TimeSpan(1, 0, 0));
When the main program wants to wake up the thread early:
wakeUpEvent.Set();
Note: You can either set the event to auto reset or manual reset. Auto reset means once WaitOne returns from the event, it will set it back to non signaled. This is useful if you are in a loop and you signal multiple times.
A thread can be started by waiting on a WaitObject and having the other thread calling the Set method on it. Look at the WaitHandle.WaitOne method.
Here's article that may be of help as well.