C Pthread: Kill other threads gracefully through one thread - c

I am working on a pthread problem in C.
The background of the problem: There are 5 threads using the same function, and when the core data in the shared memory hit the upper bound, all these five threads should terminate. I use semaphore to make sure only one of them executes the core data, which means only one of the five will get the end signal and then it will tell the rest to terminate. The code I wrote to achieve is:
#define THREAD_NUM 5;
int thread[THREAD_NUM];
sem_t s; /*semaphore to synchronize*/
sem_t empty; /*keep check of the number of empty buffers*/
sem_t full; /*keep check of the number of full buffers*/
void com_thread(*prt){ // I pass the id of the thread using prt
while(1){
sem_wait(&full)
sem_wait(&s)
...do something
sem_post(&s)
sem_post(&empty)
}
}
The signal will come while the while loop is running, and I tried to accept the signal at following position and then terminate all the threads.
To be honest, what I need to do is end all of the threads gracefully, and I need them to return to the main thread for thread_join() and free memory rather than simply exiting the program. So that's why I did not use exit() here.
The main idea below is terminating the other 4 threads when one of them got the signal. After that it would terminate itself.
However, it does not work as I expected.
#define THREAD_NUM 5;
int thread[THREAD_NUM];
sem_t s; /*semaphore to synchronize*/
sem_t empty; /*keep check of the number of empty buffers*/
sem_t full; /*keep check of the number of full buffers*/
void com_thread(*prt){ // I pass the id of the thread using prt
while(1){
sem_wait(&full)
sem_wait(&s)
if(signal){
int i;
int id = *((int*) prt);
for (i=0;i<THREAD_NUM;i++){
if(i != id)
pthread_exit(&thread[i]);
}
pthread_exit(&thread[id]);
}
...do something
sem_post(&s)
sem_post(&empty)
}
}
Can anyone help me with that? Or, if there is a better way to achieve this? Thanks in advance :)

You can use pthead_kill from the thread you want to terminate all other threads. Man page is at http://linux.die.net/man/3/pthread_kill. You should choose signal carefully if you want graceful termination. http://linux.die.net/man/7/signal has more details.

The easiest solution is probably to have a single global boolean variable, initially initialized to "false". All the threads check if this variable is "false" or "true", and if it's "true" they terminate.
When a single thread notices that all threads should be terminated it simply sets this flag to "true", and the other threads will notice that sooner or later.
You can check for this exit-condition in multiple places in the thread function, especially if some thread is waiting for a lock from the currently active thread (the one that sets the exit condition).

Related

Problem with pthread_cond_wait on multi-core processors

I'm writing a program which receive data from websocket and work with this data in thread pool.
I have problem with pthread_cond_wait when processor have 2 or more cores. After pthread_cond_signal signal is received by all threads which run on different cores. For example if I have 2 cores, then the signal will come to 2 threads at once, which are located on these two cores. If I have single core processor all is good.
What I have to do to get the program to work correctly on multi-core processors? So that only one thread receives the signal to start work.
I wrote an example of my code with generation random text data instead of websocket data.
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<pthread.h>
#include<unistd.h>
pthread_attr_t attrd;
pthread_mutex_t mutexQueue;
pthread_cond_t condQueue;
char textArr[128][24]; //array with random text to work
int tc; //tasks count
int gi; //global array index
void *workThread(void *args){
int ai;//internal index for working array element
while(1){
pthread_mutex_lock(&mutexQueue);
while(tc==0){
pthread_cond_wait(&condQueue,&mutexQueue); //wait for signal if tasks count = 0.
}
ai=gi;
if(gi==127)gi=0;else gi++;
tc--;
pthread_mutex_unlock(&mutexQueue);
printf("%s\r\n",textArr[ai]);
// then work with websocket data
}
}
void *generalThread(void *args){
const char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; //chars fo random text generation
int ai=0;
srand(time(NULL));
while(1){
for(int i=0;i<23;i++)textArr[ai][i]=chrs[rand()%61];//generating data instead of websocket data
textArr[ai][23]='\0';
tc++;
pthread_cond_signal(&condQueue); //Send signal for thread to begin work with data
if(ai==127)ai=0;else ai++;
}
}
int main(int argc,char *argv[]){
pthread_attr_init(&attrd);
pthread_attr_setdetachstate(&attrd,PTHREAD_CREATE_DETACHED);
pthread_t gt,wt[32];
for(int i=0;i<32;i++)pthread_create(&wt[i],&attrd,&workThread,NULL);
pthread_create(&gt,NULL,&generalThread,NULL);
pthread_join(gt,NULL);
return 0;
}
First some info:
man pthread_cond_wait
Rationale
Some implementations, particularly on a multi-processor, may sometimes cause multiple threads to wake up when the condition variable is signaled simultaneously on different processors.
man pthread_cond_signal
Rationale
Multiple Awakenings by Condition Signal
On a multi-processor, it may be impossible for an implementation of pthread_cond_signal() to avoid the unblocking of more than one thread blocked on a condition variable.
...
The effect is that more than one thread can return from its call to pthread_cond_wait() or pthread_cond_timedwait() as a result of one call to pthread_cond_signal(). This effect is called "spurious wakeup". Note that the situation is self-correcting in that the number of threads that are so awakened is finite; for example, the next thread to call pthread_cond_wait() after the sequence of events above blocks.
So far, so good, the code in your workThread is proper synchronized (but you should put the printf in the synchronized section as well) but the code in your generalThread has no synchronization at all. Encapsulate the code in the while loop with a lock / unlock.
In that case, the first awakened thread has to aquire a lock on the specified mutex, which will be owned by either another thread or the generalThread. Until the mutex is unlocked, the thread blocks (no matter the reason of its wakeup). After the aquisition, it owns the mutex and all other threads will be blocked, the generalThread inclusive.
Note: a pthread_cond_wait implicitly unlocks the specified mutex upon entering the wait state and on a wakeup it tries to aquire a lock on the specified mutex.
Adding a mutex lock to tc++ fully corrects my programs:
void *generalThread(void *args) {
const char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int ai=0;
srand(time(NULL));
while(1){
for(int i=0;i<23;i++)textArr[ai][i]=chrs[rand()%61];
textArr[ai][23]='\0';
pthread_mutex_lock(&mutexQueue); //this has been added
tc++;
pthread_mutex_unlock(&mutexQueue); //this has been added
pthread_cond_signal(&condQueue);
if(ai==127)ai=0;else ai++;
}
}

Synchronize two threads in C

I'm currently learning concurrent programming. I have two threads and I want them to act like this:
the first thread runs N times while the second one waits
when the first one is done, the second does its job and the first waits
when the second thread is done, repeat.
I'm trying to do it in C using pthread library. Here's some pseudocode (hopefully understandable)
int cnt = 0;
void* thread1(){
while(1){
// thread 1 code
cnt ++;
if(cnt == N){
let_thread2_work();
wait_thread2();
}
}
}
void* thread2(){
while(1){
wait_thread1();
// thread2 code
cnt = 0;
let_thread1_work();
}
}
Can anyone please help me ?
Like David Schwartz commented, this doesn't make a ton of sense with just thread1 and thread2 waiting on each other, not actually doing any work in parallel. But maybe eventually you want multiple "thread1"s, all processing jobs at the same time until they finish a batch of N jobs, then they all stop and wait for "thread2" to do some kind of post-processing before the pool of worker threads start back up.
In this situation I would consider using a couple condition variables, one for your worker threads to communicate to your post-processing thread that they're waiting, and one for your post-processing thread to tell the workers to start working again. You can declare a condition variable and a helper mutex in the global scope right next to your "cnt" variable, which I'm calling "jobs_done" for clarity:
#include<pthread.h>
#DEFINE NUM_WORKERS 1 // although it doesn't make sense to just have 1
#DEFINE BATCH_SIZE 50 // this is "N"
// we're going to keep track of how many jobs we have done in
// this variable
int jobs_done = 0;
// when a worker thread checks jobs_done and it's N or greater,
// that means we have to wait for the post-processing thread to set
// jobs_done back to 0. so the worker threads "wait" on the
// condition variable, and the post-processing thread "broadcasts"
// to the condition variable to wake them all up again once it's
// done its work
pthread_cond_t jobs_ready_cv;
// we're going to use this helper mutex. whenever any thread
// reads or writes to the jobs_done variable, we have to lock this
// mutex. that includes the worker threads when they check to see if
// they're ready to wake up again.
pthread_mutex_t jobs_mx;
// here's how the worker threads will communicate to the post-process
// thread that a batch is done. to make sure that all N jobs are fully
// complete before postprocessing happens, we'll use this variable to
// keep track of how many threads are waiting for postprocessing to finish.
int workers_done = 0;
// we'll also use a separate condition variable and separate mutex to
// communicate to the postprocess thread.
pthread_cond_t workers_done_cv;
pthread_mutex_t workers_done_mx;
Then in your setup code, initialize the condition variables and helper mutexes:
int main() { // or something
pthread_cond_init(&jobs_ready_cv, NULL);
pthread_mutex_init(&jobs_mx, NULL);
pthread_cond_init(&workers_done_cv, NULL);
pthread_mutex_init(&workers_done_mx, NULL);
...
}
So, your worker threads (or "thread1"), before taking a job, will check to see how many jobs have been taken. If N (here, BATCH_SIZE) have been taken, then it updates a variable to indicate that it has no work left to do. If it finds that all of the worker threads are done, then it signals the postprocess thread ("thread2") through workers_done_cv. Then, the thread waits for a signal from the postprocess thread through `
void* worker_thread(){
while(1){
/* first, we check if the batch is complete. we do this first
* so we don't accidentally take an extra job.
*/
pthread_mutex_lock(&jobs_mx);
if (jobs_done == BATCH_SIZE) {
/* if BATCH_SIZE jobs have been done, first let's increment workers_done,
* and if all workers are done, let's notify the postprocess thread.
* after that, we release the workers_done mutex so the postprocess
* thread can wake up from the workers_done condition variable.
*/
pthread_mutex_lock(&workers_done_mx);
++workers_done;
if (workers_done == NUM_WORKERS) {
pthread_cond_broadcast(&workers_done_cv);
}
pthread_mutex_unlock(&workers_done_mx);
/* now we wait for the postprocess thread to do its work. this
* unlocks the mutex. when we get the signal to start doing jobs
* again, the mutex will relock automatically when we wake up.
*
* note that we use a while loop here to check the jobs_done
* variable after we wake up. That's because sometimes threads
* can wake up on accident even if no signal or broadcast happened,
* so we need to make sure that the postprocess thread actually
* reset the variable. google "spurious wakeups"
*/
while (jobs_done == BATCH_SIZE) {
pthread_cond_wait(&jobs_ready_cv, &jobs_mx);
}
}
/* okay, now we're ready to take a job.
*/
++jobs_done;
pthread_mutex_unlock(&jobs_mx);
// thread 1 code
}
}
Meanwhile, your postprocess thread waits on the workers_done_cv immediately, and doesn't wake up until the last worker thread is done and calls pthread_cond_broadcast(&workers_done_cv). Then, it does whatever it needs to, resets the counts, and broadcasts to the worker threads to wake them back up.
void* postprocess_thread(){
while(1){
/* first, we wait for our worker threads to be done
*/
pthread_mutex_lock(&workers_done_mx);
while (workers_done != NUM_WORKERS) {
pthread_cond_wait(&workers_done_cv, &workers_done_mx);
}
// thread2 code
/* reset count of stalled worker threads, release mutex */
workers_done = 0;
pthread_mutex_unlock(&workers_done_mx);
/* reset number of jobs done and wake up worker threads */
pthread_mutex_lock(&jobs_mx);
jobs_done = 0;
pthread_mutex_unlock(&jobs_mx);
pthread_cond_broadcast(&jobs_ready_cv);
}
}
Also take heed of David Schwartz's advice that you probably don't actually need the postprocessing thread to wait on the worker threads. If you don't need this, then you can get rid of the condition variable that makes the worker threads wait for the postprocess thread, and this implementation becomes a lot simpler.
edit: mutex protected the assignment to jobs_done in postprocess_thread(), added a forgotten ampersand
One solution is to use mutex:
https://www.geeksforgeeks.org/mutex-lock-for-linux-thread-synchronization/
Another solution, but using semaphore:
https://www.geeksforgeeks.org/difference-between-binary-semaphore-and-mutex/?ref=rp
Or creating own lightthread schedule.
for exemple:
http://www.dunkels.com/adam/pt/ [edited]

Pthread synchronization using mutex not syncing words properly

The goal of this program is to copy a string taken in by user input word for word using multithreading. Each thread copies every fourth word so for instance the first thread copies the first and fifth words, the second copies the second and sixth words, etc. I have done quite a bit of research on mutex and I believe I have implemented the mutex lock properly however the string still comes up as jumbled nonsense when it prints. Can someone shed some light as to why the threads aren't synchronizing?
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
void *processString(void *);
char msg1[100];
char msg2[100];
char * reg;
char * token;
char * tokens[10];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t = PTHREAD_COND_INITIALIZER;
int main(){
int i = 0, j;
pthread_t workers[4];
printf("Please input a string of words separated by whitespace characters: \n");
scanf("%99[^\n]", msg1); //take in a full string including whitespace characters
//tokenize string into individual words
token = strtok(msg1, " ");
while(token != NULL){
tokens[i] = (char *) malloc (sizeof(token));
tokens[i] = token;
token = strtok(NULL, " ");
i++;
}
for(j = 0; j < 4; j++){
if(pthread_create(&workers[j], NULL, processString, (void *) j))
printf("Error creating pthreads");
}
for(i = 0; i < 4; i++){
pthread_join(workers[i], NULL);
}
pthread_mutex_destroy(&lock);
printf("%s\n", msg2);
return 0;
}
//each thread copies every fourth word
void *processString(void *ptr){
int j = (int) ptr, i = 0;
pthread_mutex_lock(&lock);
while(tokens[i * 4 + j] != NULL){
reg = (char *) malloc (sizeof(tokens[i * 4 + j]));
reg = tokens[i * 4 + j];
strcat(msg2, reg);
strcat(msg2, " ");
i++;
}
pthread_mutex_unlock(&lock);
return NULL;
}
As #EOF wrote in comments, mutexes provide only mutual exclusion. They prevent multiple cooperating threads from running concurrently, but they do not inherently provide any control over the order in which they are acquired by such threads. Additionally, as I described in comments myself, mutexes do provide mutual exclusion: if one thread holds a mutex then no other thread will be able to acquire that mutex, nor proceed past an attempt to do so, until that mutex is released.
There is no native synchronization object that provides directly for making threads take turns. That's not usually what you want threads to do, after all. You can arrange for it with semaphores, but that gets messy quickly as you add more threads. A pretty clean solution involves using a shared global variable to indicate which thread's turn it is to run. Access to that variable must be protected by a mutex, since all threads involved must both read and write it, but there's a problem with that: what if the thread that currently holds the mutex is not the one whose turn it is to run?
It is possible for all the threads to loop, continuously acquiring the mutex, testing the variable, and either proceeding or releasing the mutex. Unfortunately, such a busy wait tends to perform very poorly, and in general, you can't be confident that the thread that can make progress at any given point in the execution will manage to acquire the mutex in bounded time.
This is where condition variables come in. A condition variable is a synchronization object that permits any number of threads to suspend activity until some condition is satisfied, as judged by another, non-suspended thread. Using such a tool avoids the performance-draining busy-wait, and in your case it can help ensure that all your threads get their chance to run in bounded time. The general-purpose per-thread usage model for condition variables is as follows:
acquire the mutex protecting the shared variable(s) by which to judge whether I can proceed
Test whether I can proceed. If so, jump to step 5.
I can't proceed right now. Perform a wait on the condition variable.
I have awakened from the wait; go back to step 2.
Do the work I need to do.
Broadcast a signal to wake all threads waiting on the condition variable.
Release the mutex.
Variations on that are possible, but I recommend that you do not vary from it until and unless you know exactly why you want to do so, and exactly why the variation you have in mind is safe. Note, too, that when a thread performs a wait on a condition variable associated with a given mutex, it automatically releases that mutex while it waits, and re-acquires it before returning from the wait. This allows other threads to proceed in the meantime, and, in particular, to wait on the same condition variable.
As it applies to your problem, the shared state you want your threads to test is the aforementioned variable that indicates which thread's turn it is, and the the condition you want your threads to wait on is that it has become a different thread's turn (but this is implicit in the way you use the condition variable; condition variables themselves are generic). Note also that this means that part of the work each thread must do before signaling the other threads is to update which thread's turn it is. And since each thread may need to take multiple turns, you will want to wrap the whole procedure in a loop.

My Posix Thread wakes up without a signal

I'm trying to implement a blocking queue using POSIX threads. Important code segments are shown below. I tried to run this program. The thread trying to remove an element from the queue goes to sleep when there are no elements in the queue and wakes up again without any signal from the thread that adds an element into the queue (This I conclude because I did not start any thread that adds an element into the queue). The thread woke up again goes to sleep and this process repeats. What am I doing wrong? Please some one tell me what I am missing here?
struct rqueue
{
int qsize;
int capacity;
pthread_mutex_t lock;
pthread_cond_t not_empty;
pthread_cond_t not_full;
};
remove_element_method:
pthread_mutex_lock(&rq->lock);
while(rq->qsize == 0){
perror("Q size is zero going to sleep");
pthread_cond_wait(&rq->not_empty);
perror("woke up");
}
// some code
pthread_cond_signal(&rq->not_full);
pthread_mutex_unlock(&rq->lock);
add_element_method:
pthread_mutex_lock(&rq->lock);
if(rq->capacity != -1 ){
while(rq->qsize == rq->capacity){
pthread_cond_wait(&rq->not_full);
}
}
//some code
pthread_cond_signal(&rq->not_empty);
pthread_mutex_unlock(&rq->lock);
pthread_cond_wait() takes two arguments -- the second is the mutex you're holding. You're only passing it one argument.
Also, did you initialize the mutex and condition variables using pthread_mutex_init() and pthread_cond_init()?

How do I terminate a thread that is waiting for a semaphore operation

I am writing a program that uses shared memory and semaphores for ipc. There is one main server process that creates the shared memory and semaphores. Any number of client processes can attach to the shared memory and read and write to it when allowed. The semaphores provide the blocking mechanism to control reads and writes. Everything works fine except when a I try to terminate a client. The semaphore block to access the shared memory is in a thread and on process termination I have no way to release the semaphore block so the thread exits correctly. How would I go about this? This is for Linux.
To be specific, there is one shm and two sems. The first sem blocks writing, and the second blocks reading. When a client has something to write, it waits for the write sem to be 0, then sets it to 1, writes, then sets the read sem to 0 which releases the waiting server to read what the client wrote. once read the server sets the write sem back to 0 and the next client in line gets to write. It hangs on a semop call which releases when read sem is 0. This semop call is in a thread and I need to figure out how to exit that thread correctly before letting the main thread terminate.
Here is an example of what i want to do but isn't working (the sleep is pretending to be the hanging semop call):
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void termination_handler (int signum) {
printf( "Got Signal\n" );
}
void *threadfunc( void *parm ) {
struct sigaction action;
action.sa_handler = termination_handler;
sigemptyset( &action.sa_mask );
action.sa_flags = 0;
sigaction( SIGUSR1, &action, NULL );
printf("Thread executing\n");
sleep( 100 ); // pretending to be the semaphore
pthread_exit( NULL );
}
int main() {
int status;
pthread_t threadid;
int thread_stat;
status = pthread_create( &threadid, NULL, threadfunc, NULL );
if ( status < 0) {
perror("pthread_create failed");
exit(1);
}
sleep( 5 );
status = pthread_kill( threadid, SIGUSR1 );
if ( status < 0 )
perror("pthread_kill failed");
status = pthread_join( threadid, (void *)&thread_stat );
if ( status < 0 )
perror("pthread_join failed");
exit( 0 );
}
He said, this is for Linux.
It would be useful if you could say exactly how are you doing it. I assume you are blocking in sem_wait or sem_timedwait. If your thread is blocking there and you want to interrupt it, you can use pthread_kill.
pthread_kill(blocking_thread_id, SIGUSR1);
Of course, you need to setup the proper signal handler (man sigaction) to catch SIGUSR1 and you need to check the return code of sem_wait() for EINTR, in which case you can do whatever you want to do knowing that you were interrupted and did not get the lock.
In the case you are using processes you would use simply kill() and not pthread_kill() providing the process id. (sorry, initially I misread and thought you were using threads)
I have two and a half answers for you. :)
First, your example code works for me (on Linux): the pthread_kill successfully EINTRupts the worker thread's sleep as expected after about five seconds, as revealed with a few printfs and remembering the return value of sleep. AFAICT, if you want to signal-interrupt a specific thread, you've done it.
Second, try SEM_UNDO. This flag may be set in the sem_flg member passed in the sembuf argument semop, and it will, as the name suggests, undo semaphore adjustments upon process termination. IIUC, when you kill a client, that client leaves a semaphore inappropriately locked. SEM_UNDO was made for just this circumstance.
Finally and respectfully, have you perhaps inverted the logic of semaphores here? As I read your question, a semval of zero indicates "resource free" and a semval of one is "resource locked" (quote: "...[a client] waits for the write sem to be 0, then sets it to 1, writes..."). However, if two or more writing clients are waiting for a SysV sem to drop to zero, they will all be released together when that occurs. That's rather an unpleasant race condition, which might at the least result in unanticipated semaphore decrements and increments.
Depending on your environment perhaps you could only try to take the semaphore with a timeout. After each timeout check if a close thread has been requested and simply give up and shutdown.
It may not be the best idea to use blocking mutexes/semaphores if operations on protected area may last too long for your purposes.
You can solve the issue by putting read and write requests to a queue (linked list, for example) and let the first in the queue to operate on protected area and remove it from the list once it enters the area.
In case of read-only op you may access other reads enter the protected area as well as long as the first operation is read only. When the first operation is write, protected area must be empty before allowing it to access.
List modifications must be protected by mutex (or something alike) but that is near constant time and you probably can pay that.
When threads are sitting in a queue, each has its private condition variable which you can use to wake up any of them. Condition variable must be protected by mutex too. You may store condition variable, mutex etc into a structure and put the into an array or list and store thread id with each so that it will be easy to find the thread you want to wake up.
Once thread wakes up, it first checks what was the reason it had to wake up. If exit flag is set, then the thread know to exit.

Resources