will mutex be unlock after thread terminate? - c

On my debian 11, I created two thread, canceld one of them and joined them.
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
pthread_mutex_t executant;
void *func_1 (void *arg)
{
for (;;) {
pthread_mutex_lock (&executant);
printf ("1\n");
sleep(1);
pthread_mutex_unlock (&executant);
}
return NULL;
}
void *func_2 (void *arg)
{
for (;;) {
pthread_mutex_lock (&executant);
printf ("222\n");
sleep(1);
pthread_mutex_unlock (&executant);
}
return NULL;
}
int main (void)
{
pthread_t thread_1, thread_2;
pthread_mutex_init (&executant, NULL);
pthread_mutex_lock (&executant);
assert (pthread_create (&thread_1, NULL, func_1, NULL) == 0);
assert (pthread_create (&thread_2, NULL, func_2, NULL) == 0);
pthread_mutex_unlock (&executant);
pthread_cancel (thread_1);
pthread_join (thread_1, NULL);
pthread_join (thread_2, NULL);
}
When running the program, it may print 222 without stop, or be in blocking status after print "222".
I guess the second situiation that the thread_1(func_1) had terminated before calling pthread_mutex_unlock(), making the thread_2 fail to lock the mutex.
I wonder how to solve the problem. It may be pthread_cleanup_push(), right?

Related

Why pthread_join on itself doesn't result in error or deadlock?

https://repl.it/repls/ColdSilentTriangles
#include <stdio.h>
#include <pthread.h>
pthread_t th;
void *fp(void *args) {
printf("Thread running...");
pthread_join(th, NULL);
printf("Thread waiting...");
return NULL;
}
int main(void) {
printf("Hello World\n");
pthread_create(&th, NULL, fp, NULL);
pthread_join(th, NULL);
return 0;
}
From man pthread_join,
The pthread_join() function suspends execution of the calling thread until the target thread ter-minates unless the target thread has already terminated.
Why the program doesn't result in deadlock?
Why there is no error generated?
Why "Thread waiting..." is outputed onto the screen when the pthread_join() is supposed to block the thread?
pthread_join doesn't block execution and instead returns EDEADLK in your example.

Execution of pthreads in particular order?

I am been trying to write a program (for learning) in which there will be two threads (A and B) and both threads should execute one after the another. For example, if threads just display/prints Thread A and Thread B, then they should print in that particular order forever.
The desired output is
In Thread: thread1
In Thread: thread2
In Thread: thread1
In Thread: thread2
....
The program that I have wrote uses conditional variables for synchronisation. I have tired mutex and semaphore but they do guarantee mutual exclusivity but they don't print the information in a particular order. I understand that issue is related to scheduling of the threads by scheduler and it is possible that the thread which has just released the mutex, can lock it again immediately. See this link for link for more information.
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
pthread_cond_t cond;
pthread_mutex_t mutex;
int thread1_ret = 0;
void *thread1(void *arg)
{
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("In Thread: %s\r\n", __func__);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
thread1_ret = 5;
return &thread1_ret;
}
int thread2_ret = 0;
void *thread2(void *arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("In Thread: %s\r\n", __func__);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
thread2_ret = 5;
return &thread2_ret;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&mutex, NULL);
pthread_create(&t1, &attr, thread1, NULL);
pthread_create(&t2, &attr, thread2, NULL);
pthread_attr_destroy(&attr);
void *ret;
pthread_join(t1, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
pthread_join(t2, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
return 0;
}
My program is working properly but it stops printing after some time (2-3 seconds). I couldn't locate the bug in my code. It would be great if someone direct me with some other solution to achieve the same thing in more efficient and standard method (if there are other standard and efficient methods to solve such problem statement).
Condition variable notifications get lost when no thread is waiting in pthread_cond_wait and spurious wakes-ups happen, so the code must rather wait for a change of a shared state.
Working example:
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned state = 0;
int thread1_ret = 0;
void *thread1(void *arg)
{
unsigned state_copy;
pthread_mutex_lock(&mutex);
state_copy = state;
pthread_mutex_unlock(&mutex);
while(1) {
pthread_mutex_lock(&mutex);
while(state_copy == state)
pthread_cond_wait(&cond, &mutex);
state_copy = ++state;
printf("In Thread: %s\r\n", __func__);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
thread1_ret = 5;
return &thread1_ret;
}
int thread2_ret = 0;
void *thread2(void *arg)
{
unsigned state_copy;
pthread_mutex_lock(&mutex);
state_copy = ++state;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
while (1) {
pthread_mutex_lock(&mutex);
while(state_copy == state)
pthread_cond_wait(&cond, &mutex);
state_copy = ++state;
printf("In Thread: %s\r\n", __func__);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}
thread2_ret = 5;
return &thread2_ret;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
void *ret;
pthread_join(t1, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
pthread_join(t2, &ret);
printf("Thread Returned: %d\r\n", *(int *)ret);
return 0;
}
Note that the above code signals the condition variable after releasing the mutex. That is a micro-optimization, however, if FIFO order in waking up waiting threads is required then the mutex must be locked while signalling. See pthread_cond_signal:
The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast() or pthread_cond_signal().

Detached thread won't exit although it runs pthread_exit?

I have been dealing with a problem in a thread pool for some days now. I tried all types of different things but I can't seem to solve the issue. I have made a simple version that reproduces the problem.
Code:
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
struct bsem_t bsem;
pthread_t threads[2];
/* Binary semaphore */
typedef struct bsem_t {
pthread_mutex_t mutex;
pthread_cond_t cond;
int v;
} bsem_t;
void bsem_post(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex);
bsem->v = 1;
pthread_cond_broadcast(&bsem->cond);
pthread_mutex_unlock(&bsem->mutex);
}
void bsem_wait(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex);
while (bsem->v != 1) {
pthread_cond_wait(&bsem->cond, &bsem->mutex);
}
bsem->v = 0;
pthread_mutex_unlock(&bsem->mutex);
}
/* Being called by each thread on SIGUSR1 */
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_exit(NULL);
}
/* Startpoint for each thread */
void thread_do(){
struct sigaction act;
act.sa_handler = thread_exit;
sigaction(SIGUSR1, &act, NULL);
while(1){
bsem_wait(&bsem); // Each thread is blocked here
puts("Passed semaphore");
}
}
/* Main */
int main(){
bsem.v = 0;
pthread_create(&threads[0], NULL, (void *)thread_do, NULL);
pthread_create(&threads[1], NULL, (void *)thread_do, NULL);
pthread_detach(threads[0]);
pthread_detach(threads[1]);
puts("Created threads");
sleep(2);
pthread_kill(threads[0], SIGUSR1);
pthread_kill(threads[1], SIGUSR1);
puts("Killed threads");
sleep(10);
return 0;
}
What the code does, is create two threads. Both threads wait on a binary semaphore (bsem_wait). Then while they are waiting I send a SIGUSR1 signal to both resulting on pthread_exit() being executed on each thread. On my terminal it shows that everything goes as planned..
Output:
Created threads
Killed threads
2695145216: pthread_exit()
2686752512: pthread_exit()
The problem
Although the output seems correct, using pstree shows that only one of two threads die. The other thread stays alive until the whole program exits. Why is this?
Update
Replacing my custom binary semaphore with a normal semaphore seems to solve this for no apparent reason..
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <semaphore.h>
sem_t sem;
pthread_t threads[2];
/* Caller thread will exit */
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_exit(NULL);
}
/* Startpoint for each thread */
void* thread_do(){
struct sigaction act;
act.sa_handler = thread_exit;
sigaction(SIGUSR1, &act, NULL);
while(1){
sem_wait(&sem); // Each thread is blocked here
puts("Passed semaphore");
}
}
/* Main */
int main(){
sem_init(&sem, 0, 0); // Normal semaphore
pthread_create(&threads[0], NULL, thread_do, NULL);
pthread_create(&threads[1], NULL, thread_do, NULL);
pthread_detach(threads[0]);
pthread_detach(threads[1]);
puts("Created threads in pool");
sleep(2);
//PROBLEM
pthread_kill(threads[0], SIGUSR1);
pthread_kill(threads[1], SIGUSR1);
puts("Destroyed pool");
sleep(10);
return 0;
}
You can't get there from here
pthread_exit() is not listed in the "signal safe funtions" of the signal(7) man page.
rewrite your code to have the pthread_exit call outside of the signal handler.
So the issue seemed to be a deadlock!
The problem is that each thread is waiting inside the bsem_wait of the binary semaphore in different locations:
void bsem_wait(bsem_t *bsem) {
pthread_mutex_lock(&bsem->mutex); // THREAD 2 BLOCKED HERE
while (bsem->v != 1) {
pthread_cond_wait(&bsem->cond, &bsem->mutex); // THREAD 1 WAITING HERE
}
bsem->v = 0;
pthread_mutex_unlock(&bsem->mutex);
}
Thread 1 in this case is the fastest thread. Thread 2 is the slower one. When I run the signal to kill a thread, the waiting thread unblocks and exits as expected. The problem is that it never unlocks the mutex. So the blocked thread (2) remains blocked forever. For some reason, the thread won't be terminated because it is waiting on the mutex.
Just adding an unblock before exiting, solves the issue:
void thread_exit(){
printf("%u: pthread_exit()\n", (int)pthread_self());
pthread_mutex_unlock(&mutex); // NEW CODE
pthread_exit(NULL);
}
This ofcourse is a hack to demonstrate what is happening and shouldn't be used. I am going to follow Jasen's advice and get rid of the signal handler all together and solve it some other way. Namely I have to assure that the thread goes through the whole bsem_wait!

pthread_join function kill the thread after execution or we need to call pthread_cancel/pthread_exit?

pthread_join() function kill the thread after execution or we need to call pthread_cancel()/pthread_exit()?
I am calling pthread_cancel()/pthread_kill() which is returning 3 ie no thread attached with thread_id.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
void * run (void *);
int main() {
pthread_t p1, p2;
int a = 9;
printf("%d\n", pthread_create(&p1, NULL, &run, (void*)&p1));
printf("%d\n", pthread_create(&p2, NULL, &run, (void*)&p2));
printf("%d\n", pthread_join(p1, NULL));
//usleep(1000);
printf("%d\n", pthread_join(p2, NULL));
printf("before exit\n");
printf("%d\n", pthread_cancel(p1));
printf("after exit\n");
printf("%d\n", pthread_cancel(p2));
printf("both thread exited\n");
printf("%d\n", pthread_join(p1, NULL));
printf("%d\n", pthread_join(p2, NULL));
printf("terminated\n");
printf("%d\n", pthread_kill(p1, 0));
printf("%d\n", pthread_kill(p2, 0));
printf("ext\n");
printf("%d\n", pthread_join(p1, NULL));
printf("%d\n", pthread_join(p2, NULL));
printf("jion\n");
return 0;
}
void *run (void *p) {
int *i = (int*)p;
printf("created i = %d\n", *i);
}
This is the code i am using. in this pthread_cancel on wards all function returning 3 which means thread is being already killed.
pthread_join does not kill the thread, it waits for the thread to complete. If you want to kill a thread then use pthread_kill. But that has to be done before pthread_join, otherwise the thread has already exited.
pthread_cancel requests that the thread teminate at the next cancellation point, and is probably safer than using pthread_kill.
pthread_exit exits the current thread.
Some context would be nice... but if you're just waiting for a thread (presumably you only have one you care about) to terminate/return, then pthread_join is good enough.
The pthread_join() function waits for the thread specified by thread
to terminate. If that thread has already terminated, then pthread_join() returns
immediately.
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_join.3.html
Check the man page for usage/warnings.
After pthread_join() Add
/* Last thing that main() should do */
pthread_exit(NULL);
For more details pls refer here.
pthread_join() is used to make the main() thread wait till all the threads completes it's execution. Control reaches the pthread_join(), when that particular thread completes it's execution.
So if you try to cancel/kill that particular thread, error will be returned.
Sample Code
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 4
void *BusyWork(void *t)
{
int i;
long tid;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
pthread_exit((void*) t); //Exits that current thread.
}
int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
int rc;
long t;
void *status;
for(t=0; t<NUM_THREADS; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], NULL, BusyWork, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Wait for completion */
for(t=0; t<NUM_THREADS; t++) {
rc = pthread_join(thread[t], &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL); // Exits main thread.
}
For #Joachim Pileborg
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 4
void *BusyWork(void *t)
{
int i;
long tid;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
for(i = 0; i <10000000; i++)
printf("\n Thread: %ld, %d", tid, i);
pthread_exit((void*) t); //Exits that current thread.
}
int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
int rc;
long t;
void *status;
for(t=0; t<NUM_THREADS; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], NULL, BusyWork, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
//printf("Main: program completed. Exiting.\n");
pthread_exit(NULL); // Exits main thread(work will be done).
//return 0;//( Threads will exit once main exits.)
}

Problem while compiling pthreads program

I tried to compile this simple pthreads program with this command
$ gcc -pthread -o pthreads pthreads.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void *myThread(void *arg);
int main()
{
pthread_t mythread;
int ret;
ret = pthread_create( &mythread, NULL, myThread, NULL );
if (ret != 0){
printf( "Can't create pthread: %s", strerror(errno));
exit(-1);
}
return 0;
}
void *myThread(void *arg){
// Thread code goes here..
printf("OK! NOW ON THE THREAD\n");
pthread_exit(NULL);
}
but when trying ./pthreads there is no output presented!!
You need to wait for the thread to finish. Otherwise you risk exiting before the thread starts executing.
...
pthread_create( &mythread, NULL, myThread, NULL );
...
// Wait for the thread to finish.
pthread_join( mythread, NULL);
You didn't wait for your thread to finish. You need to use pthread_join().
You problem comes from the fact that you're main thread is returning from main, and thus calling exit (or _exit). All running thread are killed when the program exit. In this case, the worker thread didn't have the time to execute before it is killed.
You can use pthread_join to wait for the completion of the thread before returning from main.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void *myThread(void *arg);
int main()
{
void* thread_return;
pthread_t mythread;
int ret;
ret = pthread_create(&mythread, NULL, myThread, NULL);
if (ret != 0)
{
printf("Can't create pthread: %s\n", strerror(errno));
exit(-1);
}
ret = pthread_join(mythread, &thread_return);
if (ret != 0)
{
printf("Can't join pthread: %s\n", strerror(errno));
exit(-1);
}
return 0;
}
void *myThread(void *arg)
{
printf("OK! NOW ON THE THREAD\n");
pthread_exit(NULL);
}
Sanjit's answer is certainly correct, but for the sake of enlarging your threads toolbox, you might also look at pthread_barrier_wait. When you have a simple program with a lot of threads and main looks like "start all worker threads and wait for them to finish", having main and all the workers simply wait on a barrier can be a nice way to avoid having to store all the worker thread ids and join them in a for loop. Barriers also have a lot of other neat uses that sometimes let you avoid unnecessary complexity from doing the same things with mutexes and condition variables.

Resources