pthread join child thread in both thread function and cancellation handler? - multithreading

I got the following scenario with a concurrency problem, implemented using pthread library:
I got a thread that might be cancelled at any time. When that thread is cancelled, it needs to cancel its child thread, and make sure its child thread is already cancelled before it terminates.
So I end up with calling pthread_join twice on the child thread, once in the thread routine (as when the thread is not cancelled, I need that result), once in the thread's cancellation cleanup handler.
However, pthread_join doesn't allow joining the same thread twice, so what will happen?
Below is pseudo code:
void CleanupFunc(void* ChildThread)
{
pthread_cancel(*(pthread_t*)ChildThread);
pthread_join(*(pthread_t*)ChildThread, NULL);
}
void* ThreadFunc(void* _)
{
pthread_t ChildThread;
pthread_cleanup_push(&CleanupFunc, &ChildThread);
pthread_create(&ChildThread, NULL, &ChildThreadFunc, NULL);
pthread_join(ChildThread, NULL);
pthread_cleanup_pop(0);
}
Thanks in advance!

However, pthread_join doesn't allow joining the same thread twice, so what will happen?
The thread is no longer joinable, so the result is undefined behavior.
Per the POSIX standard documentation for pthread_join():
The behavior is undefined if the value specified by the thread
argument to pthread_join() does not refer to a joinable thread.

Related

What happens to a thread calling pthread_cond_signal?

When a thread calls pthread_cond_signal, one of the threads waiting on the condition will resume its execution. But what happens to the calling thread? Does it waits for the called thread to release the mutex and then it resumes?
For example, the waiting thread:
pthread_mutex_lock(&mut);
// ...
pthread_cond_wait(&cond, &mut);
// ...
pthread_mutex_unlock(&mut);
And the signaling thread:
pthread_mutex_lock(&mut);
// ...
pthread_cond_signal(&cond);
// ... has work to finish
pthread_mutex_unlock(&mut);
In this case, how can the signaling thread continue its work if the waiting thread has taken over the mutex?
The thread that calls pthread_cond_signal returns immediately. It does not wait for the woken thread (if there is one) to do anything.
If you call pthread_cond_signal while holding the mutex that the blocked thread is using with pthread_cond_wait, then the blocked thread will potentially wake from the condition variable wait, then immediately block waiting for the mutex to be acquired, since the signalling thread still holds the lock.
For the best performance, you should unlock the mutex prior to calling pthread_cond_signal.
Also, pthread_cond_wait may return even though no thread has signalled the condition variable. This is called a "spurious wake". You typically need to use pthread_cond_wait in a loop:
pthread_mutex_lock(&mut);
while(!ready){
pthread_cond_wait(&cond,&mut);
}
// do stuff
pthread_mutex_unlock(&mut);
The signalling thread then sets the flag before signalling:
pthread_mutex_lock(&mut);
ready=1
pthread_mutex_unlock(&mut);
pthread_cond_signal(&cond);

How does Rust handle killing threads?

Is there a parent-child connection between threads that are spawned?
If I kill the thread from where I spawned other threads, are those going to get killed too? Is this OS specific?
How does Rust handle killing threads?
It doesn't; there is no way to kill a thread.
See also:
How to terminate or suspend a Rust thread from another thread?
How to check if a thread has finished in Rust?
Is there a parent-child connection between threads that are spawned?
When you spawn a thread, you get a JoinHandle that allows you to wait for the child thread to finish. The child does not know of the parent.
[what happens to the other threads] in the context of a thread panicking and dying
The documentation for thread::spawn covers this well:
The join handle will implicitly detach the child thread upon being
dropped. In this case, the child thread may outlive the parent (unless
the parent thread is the main thread; the whole process is terminated when
the main thread finishes). Additionally, the join handle provides a join
method that can be used to join the child thread. If the child thread
panics, join will return an Err containing the argument given to
panic.
That is, once a child thread has been started, what happens to the parent thread basically doesn't matter, unless the parent thread was the main thread, in which case the entire process is terminated.

missed signal in c++11 condition variable

I have a small doubt about thread being woken up and unavailability of the lock
std::mutex mut;
std::queue<data_chunk> data_queue;
std::condition_variable data_cond;
void data_preparation_thread() {
while(more_data_to_prepare()) {
data_chunk const data=prepare_data();
std::lock_guard<std::mutex> lk(mut);
data_queue.push(data);
data_cond.notify_one(); //mutex is still locked here
}
}
void data_processing_thread() {
while(true) {
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[]{return !data_queue.empty();}); //what if lk could not acquire the mutex.
data_chunk data=data_queue.front();
data_queue.pop();
lk.unlock();
process(data);
if(is_last_chunk(data))
break;
}
}
In the above example data_preparation_thread() puts data in the queue and notifies and thread waiting on the condition_variable.
My question, if the other thread wakes up and finds the associated mutex is still not available, it sleeps again. Isn't it a condition of missed signal ?
if the other thread wakes up and finds the associated mutex is still not available, it sleeps again
Once it re-acquires the mutex it proceeds to test the condition.
Condition variable notification is essentially a hint that the condition may have changed and needs to be re-evaluated. There can be spurious wake-ups. The code waits for the condition to become true, not for the signal.
There's a difference between "sleeping" on the condition variable (i.e. waiting for a signal) and "sleeping" on the mutex (i.e. waiting to lock it).
If the thread wakes up from waiting on the condition variable and the mutex is still locked it starts waiting on the mutex, until it can acquire it and then check the condition (i.e. the predicate). That's not the same as waiting on the condvar again, so nothing has been missed. It's still waiting to check if the condition is true, which it can't do until it acquires the mutex lock.
Assuming that you correctly check the condition when waking (which is what the predicate you pass to condition_variable::wait does) then you won't miss the event that caused the signal.

Thread deletion design

I have multi thread program. I have a design of my application as follows:
Suppose one is main thread, and other are slave threads. Main thread keep track of all slave thread ID's. During one of the scenario of application (one of the scenario is graceful shutdown of application), i want to delete slave threads from main thread.
Here slave threads may be executing i.e., either in sleep mode or doing some action which i cannot stop the action. So i want to delete the threads from main thread with thread IDs i stored internally.
Additional info:
While deleting i should not wait for thread current action to complete as it may take long time as i am reading from data base and taking some action in thread, in case of gracefull shut down i should not wait for action to complete as it may take time.
If i force delete a thread how can there will be a resource leaks?
Is above design is ok or there is any flow or any ways we can improve the design.
Thanks!
It's not okay. It's a bad practice to forcefully kill a thread from another thread because you'll very likely to have resource leaks. The best way is to use an event or signal to signal the client process to stop and wait until they exit gracefully.
The overall flow of the program would look like this:
Parent thread creates an event (say hEventParent). it then creates child threads and passes hEventParent as a parameter. The Parent thread keeps the hThread of the child thread(s).
Child threads do work but periodically waits for hEventParent.
When the program needs to exit, the parent thread sets hEventParent. It then waits for hThread (WaitForMultipleObjects also accepts hThread)
Child thread is notified then execute clean up routine and exits.
When all the threads exit, the parent can then exit.
The most common approach consists in the main thread sending a termination signal to all the threads, then waiting for the threads to end.
Typically the worker threads will have a loop, inside of which the work is done. You can add a boolean variable that indicates if the thread needs to end. For example:
terminate = false;
while (!terminate) {
// work here
}
If you want your worker threads to go to sleep when they have no work, then it gets a bit more complicated. In this case you could make the threads wait on semaphores. Each semaphore will be signaled when there is work to do, and that will awaken the thread. You will also signal the semaphore when the request to terminate is issued. Example worker thread:
terminate = false;
while (!terminate) {
// work here
wait(semaphore); // go to sleep
}
When the main thread wants to exit it will set terminate to true for all the threads and then signal the thread semaphores to awaken the threads and give them a chance to see the termination request. After that it will join all the threads, and only after all the threads are finished it will exit.
Note that the terminate boolean may need to be declared as volatile if you are using C/C++, to indicate to the compiler that it may be changed from another thread.

Do I have to pthread_join each thread I create?

From pthread_join() man page :
When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until thread performs pthread_join on it. Therefore, pthread_join must be called once for each joinable thread created to avoid memory leaks.
Does it mean i need to join each thread i create to prevent leaks? But joining blocks the caller.
Please, explain more.
You don't need to join a thread, but it is a good idea. Without calling pthread_join(), there is a possibility that the main() function will return before the thread terminates. In this case, pthread_join() makes the application wait until the other thread finishes processing. Plus, when you join the thread, it gives you the opportunity to check for return values and make sure that everything went smoothly, and it gives you the opportunity to clean up any resources you may have shared with the thread.
EDIT: A function that may be of interest to you is pthread_detach(). pthread_detach() allows the thread's storage to be cleaned up after the thread terminates, so there is no need to join the thread afterwards.

Resources