I a have a C program which calls to threads.
iret1 = pthread_create( &thread1, NULL, readdata, NULL);
iret2 = pthread_create( &thread2, NULL, timer_func, NULL);
pthread_join(thread2, NULL);
Thread 2 returns after performing some function, after which I want to stop the execution of thread 1. How should I do this?
You can stop the thread using pthread_cancel:
pthread_cancel(thread1);
And in readdata:
/* call this when you are not ready to cancel the thread */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
...
/* call this when you are ready to cancel the thread */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
See the pthread_cancel man page for more information - there's an example included.
If you don't want to use pthread_cancel, you can use a global flag that is set by the main thread and read by thread 1. Also, you can use any of the IPC methods, like establishing a pipe between the threads.
You should signal to the thread that you wish it to stop work, and then wait for it to do so. For example, you could set a boolean flag that the thread tests regularly. If that flag indicates that work has been cancelled, then the thread should return from the thread function.
Don't attempt to forcibly terminate the thread from the outside because this will leave synchronisation objects in indeterminate state, lead to deadlocks etc.
Thread1 must have a flag which it verifies from time to time to see if it should abort itself.
There are ways to abort a thread from outside, but this is very dangerous. Don't.
Something like:
thread1stop=TRUE; //Thread 1 has access to this boolean value
pthread_join(thread1, NULL);
tkill(tid, SIGTERM) is the call you are looking for I do believe.
You can stop thread1 by calling pthread_cancel(thread1).
pthread_cancel() function sends a cancellation request to the thread.
After sending the request to cancel the thread you should check the return code to confirm that the thread was actually cancelled or not.
Here is a simple example:
rc = pthread_cancel(iret2);
if(rc) printf("failed to cancel the thread\n");
For further reference:
http://cursuri.cs.pub.ro/~apc/2003/resources/pthreads/uguide/users-39.htm
Other sources which might be useful to you.
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_create.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cancel.3.html
Related
For example, If I create 3 threads and join them in the same order. If the second thread exit first, then what would happen to the pthread_join. Will the program block until tid1 exits or directly return from pthread_join(&tid2,NULL)?
pthread_t tid1,tid2,tid3;
pthread_create(&tid1, NULL, SomeFun, NULL);
pthread_create(&tid2, NULL, SomeFun, NULL);
pthread_create(&tid3, NULL, SomeFun, NULL);
pthread_join(&tid1, NULL);
pthread_join(&tid2, NULL);
pthread_join(&tid3, NULL);
when you code calls:
pthread_join(&tid1, NULL);
if tid1 has not exited yet, then that call will block until it does. if tid2 exits in the meantime, that doesn't change the behavior of this particular call. But in that scenario, when the call does return, the next call:
pthread_join(&tid2, NULL);
will return immediately since the tid2 has already exited.
If you want to immediately perform some work when an arbitrary thread is finished, you'll need to use something other than pthread_join() to synchronize with the "some thread is finished" event. Perhaps waiting on a condition variable that gets signaled by every thread when they complete (along with some mechanism such as a queue so the waiting thread can determine which thread has signaled completion). Another mechanism that could be used is to have threads write information to a pipe that the main (or controlling) thread reads to get that notification.
If you join a thread that has already ended, pthread_join will return immediately (and destroy the thread object, like it normally does).
According to the manual page:
The pthread_join() function shall suspend execution of the calling
thread until the target thread terminates, unless the target thread
has already terminated.
So, as I understand, the calling process will block until the specified thread exit.
Now consider the following code:
pthread_t thrs[NUMTHREADS];
for (int i = 0; i < NUMTHREADS; i++)
{
pthread_create(&thrs[i], NULL, thread_main, NULL);
}
pthread_join(thrs[0], NULL); /* will be blocked here */
pthread_join(thrs[1], NULL);
pthread_join(thrs[2], NULL);
/* ... */
pthread_join(thrs[NUMTHREADS - 1], NULL);
The calling thread will be blocked in the call to pthread_join(thrs[0], NULL), until thrs[0] exit in some way. But how if another thread, for example, thrs[2] call pthread_exit() while we are blocked in the call to pthread_join(thrs[0], NULL)? Do we have to wait for thrs[0] to exit in order to receive the return value of thrs[2]?
But how if another thread, say thrs[2] exit while we are blocked in
the call to pthread_join(thrs[0], NULL)?
Yes, it could happen. In that case, pthread_join(thrs[2], NULL); will return immediately.
Do we have to wait for thrs[0] to exit in order to receive the return
value of thrs[2]?
Yes, you have to wait for thr[0] to terminate.
(Not directly related to the question)
It's not necessary to call pthread_join() on every thread you create. It's a convenient function to get the return status from thread(s). If you don't need to know the termination status of the thread, you could
create the thread by seeting the "detached" attribute or call pthread_detach(pthread_self()); from the thread itself to make it detached.
In some cases, you would want the threads created to continue execution but no longer need the main thread. In that case, you could call pthread_exit(NULL); from main thread which will let other threads to continue even after main thread exits.
Yes - the main thread blocked on thrs[0] will not get the result from thrs[2] until after thrs[[0] and thrs[1] have also exited.
If you need more flexibility one option is to do something like having the threads post their results in a queue or signal in some other way that the thread needs to be joined. The main thread can monitor that queue/signal and get the necessary results (which could come from a pthread_join() that is done on the thread that is known to be completed from information int he queue/signal).
Yes. The code is executed in serial.
This code plays a sound clip by creating a thread to do it. When bleep() runs, it sets the global variable bleep_playing to TRUE. In its main loop, if it notices that bleep_playing has been set to FALSE, it terminates that loop, cleans up (closing files, freeing buffers), and exits. I don't know the correct way to wait for a detached thread to finish. pthread_join() doesn't do the job. The while loop here continually checks bleep_id to see if it's valid. When it isn't, execution continues. Is this the correct and portable way to tell a thread to clean up and terminate before the next thread is allowed to be created?
if (bleep_playing) {
bleep_playing = FALSE;
while (pthread_kill(bleep_id, 0) == 0) {
/* nothing */
}
}
err = pthread_create(&bleep_id, &attr, (void *) &bleep, &effect);
I
Hmm... pthread_join should do the job. As far as I remember the thread has to call pthread_exit...?
/* bleep thread */
void *bleep(void *)
{
/* do bleeping */
pthread_exit(NULL);
}
/* main thread */
if (pthread_create(&thread, ..., bleep, ...) == 0)
{
/*
** Try sleeping for some ms !!!
** I've had some issues on multi core CPUs requiring a sleep
** in order for the created thread to really "exist"...
*/
pthread_join(&thread, NULL);
}
Anyway if it isn't doing its thing you shouldn't poll a global variable since it will eat up your CPU. Instead create a mutex (pthread_mutex_*-functions) which is initially locked and freed by the "bleep thread". In your main thread you can wait for that mutex which makes your thread sleep until the "bleep thread" frees the mutex.
(or quick & and dirty: sleep for a small amount of time while waiting for bleep_playing becoming FALSE)
I'm writing a code in which I have two threads running in parallel.
1st is the main thread which started the 2nd thread.
2nd thread is just a simple thread executing empty while loop.
Now I want to pause / suspend the execution of 2nd thread by 1st thread who created it.
And after some time I want to resume the execution of 2nd thread (by issuing some command or function) from where it was paused / suspended.
This question is not about how to use mutexes, but how to suspend a thread.
In Unix specification there is a thread function called pthread_suspend, and another called pthread_resume_np, but for some reason the people who make Linux, FreeBSD, NetBSD and so on have not implemented these functions.
So to understand it, the functions simply are not there. There are workarounds but unfortunately it is just not the same as calling SuspendThread on windows. You have to do all kinds of non-portable stuff to make a thread stop and start using signals.
Stopping and resuming threads is vital for debuggers and garbage collectors. For example, I have seen a version of Wine which is not able to properly implement the "SuspendThread" function. Thus any windows program using it will not work properly.
I thought that it was possible to do it properly using signals based on the fact that JVM uses this technique of signals for the Garbage collector, but I have also just seen some articles online where people are noticing deadlocks and so on with the JVM, sometimes unreproducable.
So to come around to answer the question, you cannot properly suspend and resume threads with Unix unless you have a nice Unix that implements pthread_suspend_np. Otherwise you are stuck with signals.
The big problem with Signals is when you have about five different libraries all linked in to the same program and all trying to use the same signals at the same time. For this reason I believe that you cannot actually use something like ValGrind and for example, the Boehm GC in one program. At least without major coding at the very lowest levels of userspace.
Another answer to this question could be. Do what Linuz Torvalds does to NVidia, flip the finger at him and get him to implement the two most critical parts missing from Linux. First, pthread_suspend, and second, a dirty bit on memory pages so that proper garbage collectors can be implemented. Start a large petition online and keep flipping that finger. Maybe by the time Windows 20 comes out, they will realise that Suspending and resuming threads, and having dirty bits is actually one of the fundamental reasons Windows and Mac are better than Linux, or any Unix that does not implement pthread_suspend and also a dirty bit on virtual pages, like VirtualAlloc does in Windows.
I do not live in hope. Actually for me I spent a number of years planning my future around building stuff for Linux but have abandoned hope as a reliable thing all seems to hinge on the availability of a dirty bit for virtual memory, and for suspending threads cleanly.
As far as I know you can't really just pause some other thread using pthreads. You have to have something in your 2nd thread that checks for times it should be paused using something like a condition variable. This is the standard way to do this sort of thing.
I tried suspending and resuming thread using signals, here is my solution. Please compile and link with -pthread.
Signal SIGUSR1 suspends the thread by calling pause() and SIGUSR2 resumes the thread.
From the man page of pause:
pause() causes the calling process (or thread) to sleep until a
signal is delivered that either terminates the process or causes the
invocation of a
signal-catching function.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
// Since I have only 2 threads so using two variables,
// array of bools will be more useful for `n` number of threads.
static int is_th1_ready = 0;
static int is_th2_ready = 0;
static void cb_sig(int signal)
{
switch(signal) {
case SIGUSR1:
pause();
break;
case SIGUSR2:
break;
}
}
static void *thread_job(void *t_id)
{
int i = 0;
struct sigaction act;
pthread_detach(pthread_self());
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = cb_sig;
if (sigaction(SIGUSR1, &act, NULL) == -1)
printf("unable to handle siguser1\n");
if (sigaction(SIGUSR2, &act, NULL) == -1)
printf("unable to handle siguser2\n");
if (t_id == (void *)1)
is_th1_ready = 1;
if (t_id == (void *)2)
is_th2_ready = 1;
while (1) {
printf("thread id: %p, counter: %d\n", t_id, i++);
sleep(1);
}
return NULL;
}
int main()
{
int terminate = 0;
int user_input;
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread_job, (void *)1);
// Spawned thread2 just to make sure it isn't suspended/paused
// when thread1 received SIGUSR1/SIGUSR2 signal
pthread_create(&thread2, NULL, thread_job, (void *)2);
while (!is_th1_ready && !is_th2_ready);
while (!terminate) {
// to test, I am sensing signals depending on input from STDIN
printf("0: pause thread1, 1: resume thread1, -1: exit\n");
scanf("%d", &user_input);
switch(user_input) {
case -1:
printf("terminating\n");
terminate = 1;
break;
case 0:
printf("raising SIGUSR1 to thread1\n");
pthread_kill(thread1, SIGUSR1);
break;
case 1:
printf("raising SIGUSR2 to thread1\n");
pthread_kill(thread1, SIGUSR2);
break;
}
}
pthread_kill(thread1, SIGKILL);
pthread_kill(thread2, SIGKILL);
return 0;
}
There is no pthread_suspend(), pthread_resume() kind of APIs in POSIX.
Mostly condition variables can be used to control the execution of other threads.
The condition variable mechanism allows threads to suspend execution
and relinquish the processor until some condition is true. A condition
variable must always be associated with a mutex to avoid a race
condition created by one thread preparing to wait and another thread
which may signal the condition before the first thread actually waits
on it resulting in a deadlock.
For more info
Pthreads
Linux Tutorial Posix Threads
If you can use processes instead, you can send job control signals (SIGSTOP / SIGCONT) to the second process. If you still want to share the memory between those processes, you can use SysV shared memory (shmop, shmget, shmctl...).
Even though I haven't tried it myself, it might be possible to use the lower-level clone() syscall to spawn threads that don't share signals. With that, you might be able to send SIGSTOP and SIGCONT to the other thread.
For implementing the pause on a thread, you need to make it wait for some event to happen. Waiting on a spin-lock mutex is CPU cycle wasting. IMHO, this method should not be followed as the CPU cycles could have been used up by other processes/threads.
Wait on a non-blocking descriptor (pipe, socket or some other). Example code for using pipes for inter-thread communication can be seen here
Above solution is useful, if your second thread has more information from multiple sources than just the pause and resume signals. A top-level select/poll/epoll can be used on non-blocking descriptors. You can specify the wait time for select/poll/epoll system calls, and only that much micro-seconds worth of CPU cycles will be wasted.
I mention this solution with forward-thinking that your second thread will have more things or events to handle than just getting paused and resumed. Sorry if it is more detailed than what you asked.
Another simpler approach can be to have a shared boolean variable between these threads.
Main thread is the writer of the variable, 0 - signifies stop. 1 - signifies resume
Second thread only reads the value of the variable. To implement '0' state, use usleep for sime micro-seconds then again check the value. Assuming, few micro-seconds delay is acceptable in your design.
To implement '1' - check the value of the variable after doing certain number of operations.
Otherwise, you can also implement a signal for moving from '1' to '0' state.
You can use mutex to do that, pseudo code would be:
While (true) {
/* pause resume */
lock(my_lock); /* if this is locked by thread1, thread2 will wait until thread1 */
/* unlocks it */
unlock(my_lock); /* unlock so that next iteration thread2 could lock */
/* do actual work here */
}
You can suspend a thread simply by signal
pthread_mutex_t mutex;
static void thread_control_handler(int n, siginfo_t* siginfo, void* sigcontext) {
// wait time out
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
// suspend a thread for some time
void thread_suspend(int tid, int time) {
struct sigaction act;
struct sigaction oact;
memset(&act, 0, sizeof(act));
act.sa_sigaction = thread_control_handler;
act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&act.sa_mask);
pthread_mutex_init(&mutex, 0);
if (!sigaction(SIGURG, &act, &oact)) {
pthread_mutex_lock(&mutex);
kill(tid, SIGURG);
sleep(time);
pthread_mutex_unlock(&mutex);
}
}
Not sure if you will like my answer or not. But you can achieve it this way.
If it is a separate process instead of a thread, I have a solution (This might even work for thread, maybe someone can share your thoughts) using signals.
There is no system currently in place to pause or resume the execution of the processes. But surely you can build one.
Steps I would do if I want it in my project:
Register a signal handler for the second process.
Inside the signal handler, wait for a semaphore.
Whenever you want to pause the other process, just send in a signal
that you registered the other process with. The program will go into
sleep state.
When you want to resume the process, you can send a different signal
again. Inside that signal handler, you will check if the semaphore is
locked or not. If it is locked, you will release the semaphore. So
the process 2 will continue its execution.
If you can implement this, please do share your feedack, if it worked for you or not. Thanks.
I'm using pthread_create() and pthread_cancel() functions to create a multithreaded program, but I noticed that pthread_cancel() did not really terminate the thread it was supposed to.
void check(void *param){
header_t *Bag = (header_t *) param;
pthread_t timer_thread;
while(true){
if(Bag->size && TIMER_OFF){
pthread_create(&timer_thread, NULL, (void *) &timer, (void *) Bag);
printf("\nCREATE THREAD ID = %d\n", timer_thread);
// ADD
}
else if(!TIMER_OFF && Bag->size >= 2 && Bag->next->time <= CURRENT_APT_TIME && CRRENT_TAG != Bag->next->tag){
printf("\nOLD THREAD ID = %d TO BE CANCELLED\n", timer_thread);
pthread_cancel(timer_thread);
pthread_create(&timer_thread, NULL, (void *) &timer, (void *) Bag);
printf("\nNEW THREAD ID = %d\n", timer_thread);
// Replace
}
Sleep(1);
}
}
timer function void timer(void *) is exactly what it sounds like, and I've included couple of lines to print out the thread ID of itself.
When tested, the following was seen:
...
OLD THREAD ID = 6041240 TO BE CANCELLED
NEW THREAD ID = 6046456
...
THREAD ID EXECUTING = 6041240
So the timer function was not terminated by calling pthread_cancel()?
By default your thread is created with the cancel type PTHREAD_CANCEL_DEFERRED, which means that you need to make sure that your thread has a so-called cancellation point. That is, a point where cancel requests are checked and reacted upon.
This page contains a list of functions that are guaranteed to be cancellation points. Examples are some of the sleep() and pthread functions. You can also use pthread_testcancel() if you just need a function to purely test whether the thread has been canceled, and nothing else.
Another option is to set your threads canceltype to be PTHREAD_CANCEL_ASYNCHRONOUS, by using pthread_setcanceltype(), which will make your thread cancelable even without cancellation points. However, the system is still free to choose when the thread should actually be canceled, and you'll need to take great care to make sure that the system isn't left in an inconsistent state when cancelled (typically means avoiding any system calls and similar - see the list of Async-cancel-safe functions - it's short!).
In general, asynchronous cancellation should only be used for more or less "pure" processing threads, whereas threads performing system calls and similar are better implemented with deferred cancellation and careful placement of cancellation points.
Also, as long as you are not detaching your thread (by either creating it detached through its attribute, or by calling pthread_detach() after it is created), you will need to call pthread_join() on the timer thread to make sure that all resources are cleaned up after canceling it. Otherwise you might end up in a state without any spare threading resources, where you cannot create any new threads.
The default cancel method of pthread_cancel() is delayed cancel.So when you invoke pthread_cancel(), it will not really cancel before the specified thread reach the cancel point.You shoud call pthread_setcanceltype to set another cancel method to your thread.