Mutex Deadlock (pthread_mutex) - c

I can't understand why in this code I get a deadlock.
I have defined this mutexes:
mutex3: = 0 (LOCKED)
mutex2: = 1 (UNLOCKED)
I have 2 processes: Father and son. Each has N threads that I pass by argument. The child's threads contend with the father's threads a "resource" (typical producer / consumer problem).
Thanks in advance!
I suppose the problem is here:
void * func_padre(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex2);
printf("Scrivi messaggio: ");
fflush(stdout);
scanf("%[^\n]",(char *)addr_mem);
getchar();
pthread_mutex_unlock(&mutex3);
}
}
void * func_figlio(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex3);
write(fd,addr_mem,4096);
lseek(fd,0,SEEK_SET);
memset(addr_mem,0,4096);
pthread_mutex_unlock(&mutex2);
}
}
CODE:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
void * addr_mem;
pthread_mutex_t mutex2,mutex3;
int fd;
void * func_padre(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex2);
printf("Scrivi messaggio: ");
fflush(stdout);
scanf("%[^\n]",(char *)addr_mem);
getchar();
pthread_mutex_unlock(&mutex3);
}
}
void * func_figlio(void * n)
{
while(1)
{
pthread_mutex_lock(&mutex3);
write(fd,addr_mem,4096);
lseek(fd,0,SEEK_SET);
memset(addr_mem,0,4096);
pthread_mutex_unlock(&mutex2);
}
}
int main(int argc, char*argv[])
{
if(argc<2)
{
printf("POCHI PARAMETRI\n");
fflush(stdout);
exit(-1);
}
int val=strtol(argv[2],0,10);
fd = open(argv[1],O_CREAT|O_RDWR,0666);
lseek(fd,0,SEEK_SET);//USELESS
///SHARED MEMORY
int id_mem;
id_mem = shmget(6543,4096,IPC_CREAT|0666);
addr_mem = shmat(id_mem,NULL,0);
/////////////////////
/// MUTEX
pthread_mutex_init(&mutex2,NULL);
pthread_mutex_init(&mutex3,NULL);
pthread_mutex_lock(&mutex3);
/////////////////////
pthread_t tid;
int i=0;
int pid;
pid = fork();
if(pid==0)
{
//CHILD
for(i=0; i<val; i++)
pthread_create(&tid,NULL,func_figlio,NULL);
while(1)
{
pthread_mutex_lock(&mutex3);
write(fd,addr_mem,4096);
memset(addr_mem,0,4096);
pthread_mutex_unlock(&mutex2);
}
}
else
{
//FATHER
for(i=0; i<val; i++)
pthread_create(&tid,NULL,func_padre,NULL);
while(1)
{
pthread_mutex_lock(&mutex2);
printf("Scrivi messaggio: ");
fflush(stdout);
scanf("%[^\n]",(char *)addr_mem);
getchar();
pthread_mutex_unlock(&mutex3);
}
}
}

Your problem is not a deadlock, it's just buggy code. A thread cannot unlock a mutex it did not lock. Your while loops all unlock mutexes they do not hold and never unlock the mutexes they do hold.

suggest:
have global variable that is cycled through a limited set of values, say: 0, 1, 0 ...
Use the mutex to stop other threads from progressing, I.E.
When a call (in thread) returns from locking the mutex,
then check
if the value in the global variable is for 'this' thread.
then
process the thread activities,
increment the global variable,
endif
endif
unlock the mutex
call nanosleep() to delay for a while to allow other threads to run

Related

process stuck in waiting

I'm having trouble with threads synchronization on Linux. I must generate the process hierarchy from this picture ( this part i managed to do).
But next I have to synchronize threads from different processes. The process P2 must create 6 threads and the process P6 must create 5 threads. And then the thread 5 from P2 must only start after the thread 3 from P6 has completed. I use conditional variables, but while I'm waiting for the thread 3 from P6 to end, process 2 remain blocked and I never reach to process 6 to create his threads. The function info is used to display the beginning and the end of the thread.
I cannot use sleep or usleep
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
pthread_cond_t p2_t4=PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1=PTHREAD_MUTEX_INITIALIZER;
int end=-1;
void* function(void* arg)
{
int* nrth=(int*) arg;
info(BEGIN,6,*nrth);
info(END,6,*nrth);
pthread_mutex_lock(&lock1);
if(*nrth==3)
{
end=1;
pthread_cond_signal(&p2_t4);
}
pthread_mutex_unlock(&lock1);
return 0;
}
void* function2(void* arg)
{
int* nrth=(int*) arg;
pthread_mutex_lock(&lock1);
if(*nrth==4)
{
while(end==-1)
pthread_cond_wait(&p2_t4,&lock1);
}
pthread_mutex_unlock(&lock1);
info(BEGIN,2,*nrth);
info(END,2,*nrth);
return 0;
}
int main()
{
pthread_t threads[6];
int index[5];
pthread_t threads2[7];
int index2[7];
if(fork()!=0)
{
//info(BEGIN,1,0);
wait(NULL);
if(fork()!=0)
{
wait(NULL);
}
else
{
//info(BEGIN,3,0);
if(fork()!=0)
{
wait(NULL);
if(fork()!=0)
{
wait(NULL);
}
else
{
//info(BEGIN,6,0);
for(int i=1; i<=5; i++)
{
index[i]=i;
pthread_create(&threads[i],NULL,function,&index[i]);
}
for(int i=1; i<=5; i++)
{
pthread_join(threads[i],NULL);
}
//info(END,6,0);
//info(END,3,0);
//info(END,1,0);
}
}
else
{
//info(BEGIN,5,0);
//info(END,5,0);
}
}
}
else
{
//info(BEGIN,7,0);
wait(NULL);
for(int i=1; i<=6; i++)
{
index2[i]=i;
pthread_create(&threads2[i],NULL,function2,&index2[i]);
}
for(int i=1; i<=6; i++)
{
pthread_join(threads2[i],NULL);
}
if(fork()!=0)
{
wait(NULL);
if(fork()!=0)
{
wait(NULL);
}
else
{
//info(BEGIN,7,0);
//info(END,7,0);
//info(END,2,0);
}
}
else
{
//info(BEGIN,4,0);
//info(END,4,0);
}
}
return 0;
}
To generate that process tree the main process must do 2 calls to fork to create 2 child processes. This code blocks the main process after the first fork. The process creating code must be redone.
The mutexes and condition variables are not shared between the processes because each process has its own private address space. The mutexes and condition variables must be placed in shared memory in order to be shared across processes. Alteratively, use POSIX semaphores.

Synchronize threads from different processes using semaphore

I have problem with semaphore in C. I have a parent process and a child process. Both can create 3 threads and I must display the beginning and the end of threads and I must impose the next condition: the thread with id 1 from parent process must display its beginning after the thread with id 2 from child process display its end. I use a semaphore, but when I do wait, the thread with id 1 from parent process it doesn't remain stuck at semaphore and continue to display the beginning. I can't use function usleep() or sleep().
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <semaphore.h>
sem_t* s=NULL;
void* function1(void* arg)
{
int* nrth=(int*) arg;
sem_t * s=NULL;
s=sem_open("mysemaphore",O_EXCL);
if(s==NULL)
perror("Error");
if(*nrth==1)
sem_wait(s);
printf("Begin P1, thread %d\n",*nrth);
printf("End P1, thread %d\n",*nrth);
sem_close(s);
return 0;
}
void* function2(void* arg)
{
int* nrth=(int*) arg;
sem_t * s=NULL;
s=sem_open("mysemaphore",O_EXCL);
if(s==NULL)
perror("Error");
printf("Begin P2, thread %d\n",*nrth);
printf("End P2, thread %d\n",*nrth);
if(*nrth==2)
sem_post(s);
sem_close(s);
return 0;
}
int main()
{
sem_unlink("mysemaphore");
s=sem_open("mysemaphore",O_CREAT,0644,1);
if(s==NULL)
perror("ERROR!");
pthread_t threads[4];
int index[4];
pthread_t threads2[4];
int index2[4];
if(fork()==0)
{
printf("Begin: process 2 \n");
for(int i=1; i<=3; i++)
{
index2[i]=i;
pthread_create(&threads2[i],NULL,function2,&index2[i]);
}
for(int i=1; i<=3; i++)
{
pthread_join(threads2[i],NULL);
}
printf("End: process 2 \n");
}
else
{
printf("Begin: process 1\n");
for(int i=1; i<=3; i++)
{
index[i]=i;
pthread_create(&threads[i],NULL,function1,&index[i]);
}
for(int i=1; i<=3; i++)
{
pthread_join(threads[i],NULL);
}
printf("End: process 2 \n");
wait(NULL);
}
return 0;
}
You are destroying your semaphore in both function1() and function2() when you call sem_destroy(), after which the behavior of that semaphore is undefined. That may be your biggest problem.
You should be using sem_close() instead after you are finished using the semaphore that you obtained from sem_open().

Threads are created, then all exit before critical region

I need to write a program for class that creates 8 threads. 4 producer, and 4 consumer. The producers need to loop, and randomly send SIGUSR1 or SIGUSR2 to all consumer threads. Only 2 should register if they have received SIGUSR1 and the other 2 register SIGUSR2.
When I try to run it all threads are created, "prod ready" is printed by all 4 producer threads,"waiting 1" is printed by both threads, but "waiting 2" is printed 3 times then all threads exit. At the end of debugging it says that the process exits normally.
I need to use semaphores to control the critical regions. Any help would be great.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <signal.h>
#define NP 4
#define NC1 2
#define NC2 2
#define CNT 10
void handler1(int signum);
void handler2(int signum);
typedef struct {
int sent;
int received;
int buf[1];
int SIG1;
int SIG2;
sem_t con;
sem_t prod;
} sbuf_t;
sbuf_t buff;
void *producer() {
printf("prod ready \n");
int s;
while(1){
sem_wait(&buff.prod);
s=rand()%2;
if(s==1){
buff.sent++;
kill(0,SIGUSR1);
}
else if(s==2){
buff.sent++;
kill(0,SIGUSR2);
}sem_post(&buff.prod);
}
}
void *consumer1() {
signal(SIGUSR1, handler1);
printf("waiting 1\n");
while(1){
}
}
void *consumer2() {
signal(SIGUSR2, handler2);
printf("waiting 2\n");
while(1){
}
}
void handler1(int signum){
if(signum==SIGUSR1){
sem_wait(&buff.con);
printf("Caught 1\n");
buff.received++;
buff.SIG1++;
sem_post(&buff.con);
}
}
void handler2(int signum){
if(signum==SIGUSR2){
sem_wait(&buff.con);
printf("caught 2 \n");
buff.received++;
buff.SIG2++;
sem_post(&buff.con);
}
}
void main(){
pthread_t threads[9];
buff.SIG1=0;
buff.SIG2=0;
buff.sent=0;
buff.received=0;
int index;
sem_init(&buff.con, 0, 0);
sem_init(&buff.prod, 0, 0);
for (index = 0; index < NP; index++) {
pthread_create(&threads[index], NULL, producer,NULL);
}
for (index = 0;index < NC1;index++) {
pthread_create(&threads[index+4], NULL, consumer1,NULL);
}
for (index = 0;index < NC2;index++) {
pthread_create(&threads[index+6], NULL, consumer2,NULL);
}
}
In the main() function, the threads are being created,
then main() exits.
When main() exits, all the threads are also exited.
Suggest reading about such functions as: pthread_exit() and pthread_join()
Note: the following has an error in the handling of the signals and in the handling of the semaphores, but will demonstrate the use of pthread_join() and pthread_exit()
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <signal.h>
#define NP 4
#define NC1 2
#define NC2 2
#define CNT 10
#define MAX_THREADS (9)
void handler1(int signum);
void handler2(int signum);
struct sbuf_t
{
int sent;
int received;
int buf[1];
int SIG1;
int SIG2;
sem_t con1;
sem_t con2;
sem_t prod;
};
typedef struct sbuf_t myData;
myData buff;
void *producer( void *dummy )
{
(void)dummy;
printf("prod ready \n");
int s;
while(1)
{
sem_wait(&buff.prod);
s=rand()%2;
if( !s )
{
buff.sent++;
kill( 0, SIGUSR1 );
}
else // if( s )
{
buff.sent++;
kill( 0, SIGUSR2 );
}
//sem_post(&buff.prod);
}
pthread_exit( NULL );
} // end thread: producer
void *consumer1( void *dummy )
{
(void)dummy;
//signal(SIGUSR1, handler1);
printf("waiting 1\n");
while(1)
{
sem_wait( &buff.con1 );
// do something
//sem_post( &buff.prod );
}
pthread_exit( NULL );
} // end thread: consumer1
void *consumer2( void *dummy )
{
(void)dummy;
//signal(SIGUSR2, handler2);
printf("waiting 2\n");
while(1)
{
sem_wait( &buff.con2 );
// do something
//sem_post( &buff.prod );
}
pthread_exit( NULL );
} // end thread: consumer2
void handler(int signum)
{
sem_post(&buff.prod);
if(signum==SIGUSR1)
{
//sem_wait(&buff.con);
puts("Caught 1");
buff.received++;
buff.SIG1++;
sem_post(&buff.con1);
}
else if(signum==SIGUSR2)
{
//sem_wait(&buff.con);
puts("caught 2");
buff.received++;
buff.SIG2++;
sem_post(&buff.con2);
}
} // end signal handler: handler2
int main( void )
{
pthread_t threads[ MAX_THREADS ];
buff.SIG1=0;
buff.SIG2=0;
buff.sent=0;
buff.received=0;
int index;
sem_init(&buff.con1, 0, 0);
sem_init(&buff.con2, 0, 0);
sem_init(&buff.prod, 0, 0);
signal(SIGUSR2, handler);
signal(SIGUSR1, handler);
for (index = 0; index < NP; index++)
{
pthread_create(&threads[index], NULL, producer,NULL);
}
for (index = 0;index < NC1;index++)
{
pthread_create(&threads[index+4], NULL, consumer1,NULL);
}
for (index = 0;index < NC2;index++)
{
pthread_create(&threads[index+6], NULL, consumer2,NULL);
}
for( size_t x=0; x<MAX_THREADS; x++ )
{
pthread_join( threads[x], NULL );
}
} // end function: main
HOWEVER, the methods to handle signals to threads does not use kill() as that is for processes.
rather the code should use functions similar to::
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_signal(pthread_cond_t *cond)
The signaled thread should block on a pthread_cond_wait() call until another thread sends a signal using pthread_cond_signal(), with the same condition variable.
Considering the analogy with signals delivered to processes, this is a bit different because the signaled thread has already suspended its execution waiting for a signal, unlike a process that simply gets interrupted and goes on.
For you example, you are creating your producers before your consumers. Also in your producer, you are using a random number generator to determine if you issue USR1 or USR2. Your description gave the impression you wanted two of each (versus some random mix totaling 4) which is what I see the code doing for you.

Sem_wait() not blocking after first true condition

I am learning to use semaphores and below is a small scenario which I've tried to implement. Its behaving weird in a way. After sem_wait() gets unblocked first time, its not getting blocked again and keeps on looping, not getting why. Is this the right way or right scenario to use semaphore?
EDIT: I just realized that if I uncomment the sleep after sem_post, it works fine. .Reason being it was repeatedly doing sem_post() before thread could do coin=0 I believe. But is it right to use sleep this way with semaphores. I believe this would be considered a bad practice?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#define MAX_MSG_LEN 256
sem_t sem1;
sem_t sem2;
int coin=0;
void *thrdFun1(void *arg);
void *thrdFun2(void *arg);
void toggleCase(char *buf, int cnt);
int main()
{
pthread_t thrd1;
char argmsg1[] = "Thread1: Waiting to deliver\n";
int thNum;
int res;
res = sem_init(&sem1, 0,0);
// res = sem_init(&sem2, 0,0);
res = pthread_create(&thrd1, NULL, thrdFun1, argmsg1);
while(1)
{
if (coin==0)
{
printf("no coin: please enter coin\n");
scanf("%d",&coin);
}
else
{
sem_post(&sem1);
// sleep(1);
}
}
return 0;
}
void *thrdFun1(void *arg)
{
while(1)
{
printf("I'm %s\n",(char *)arg);
sem_wait(&sem1);
printf("Delivered...\n");
coin=0;
sleep(1);
}
}
Semaphores are used to control Critical-Section Access. In this case, critical section would be the output shell. The thread may or may not start promptly when the pthread_create() is called. Also, sem_wait() will decrease the value of sem1 with each call. Thus, when you include sleep(1) in the thrdFun1 function, there may be undefined behaviour :)
You need to remove sleep(1); from function thrdFun1. After this there will not be any need of sleep(1) in main.
You realized it right, it is repeatedly doing sem_post() before thread could do coin=0 when removing all sleeps.
To solve this you could use second semaphore (you already tried it seems) like below,
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#define MAX_MSG_LEN 256
sem_t sem1;
sem_t sem2;
int coin=0;
void *thrdFun1(void *arg);
void *thrdFun2(void *arg);
void toggleCase(char *buf, int cnt);
int main()
{
pthread_t thrd1;
char argmsg1[] = "Thread1: Waiting to deliver\n";
int thNum;
int res;
res = sem_init(&sem1, 0,0);
res = sem_init(&sem2, 0,0);
res = pthread_create(&thrd1, NULL, thrdFun1, argmsg1);
while(1)
{
if (coin==0)
{
printf("no coin: please enter coin\n");
scanf("%d",&coin);
}
else
{
sem_post(&sem1); // Coin is spun
sem_wait(&sem2); // Wait till it is caught
}
}
return 0;
}
void *thrdFun1(void *arg)
{
while(1)
{
printf("I'm %s\n",(char *)arg);
sem_wait(&sem1); // Wait to spin the coin
coin=0;
sem_post(&sem2); // inform as caught
printf("Delivered...\n");
}
}
there is a chance that "Thread1: Waiting to deliver" this string can get printed many times.
What you are trying to achieve is looks like producer-consumer problem.
You required two semaphore to achive this.
main function:
while(1)
{
if (coin==0)
{
printf("no coin: please enter coin\n");
scanf("%d",&coin);
}
else
{
sem_post(&sem1);
sem_wait(&sem2)
}
}
in thread function
while(1)
{
printf("I'm %s\n",(char *)arg);
sem_wait(&sem1);
printf("Delivered...\n");
coin=0;
sem_post(&sem2)
}

Global variable changes value magically in C

This will probably require some looking into, but my question is very simple:
Why is numPassenger always 0 in the parentHandler2() function?
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
#include <sys/time.h>
#include <math.h>
int getRand()
{
return (rand() % 5001);
}
//////////GLOBAL//////////
const int CAPACITY = 100;
const int MEMSIZE = 1024;
char* sharedmem;
pid_t pid;
int numPassenger;
int numTram;
//////////GLOBAL//////////
//handles SIGALRM, generates passengers, sends SIGUSR1
void parentHandler1()
{
numPassenger = getRand();
sprintf(sharedmem, "%d", numPassenger);
kill(getpid(), SIGUSR1);
}
//handles SIGUSR1, calculates number of trams needed, sends SIGUSR2
void childHandler()
{
double n = atoi(sharedmem);
numTram = (ceil(n/100));
sprintf(sharedmem, "%d", numTram);
kill(pid, SIGUSR2);
}
//outputs
void parentHandler2()
{
int n = atoi(sharedmem);
printf("Passengers: %d, Trams: %d\n", numPassenger, n);
}
int main (int argc, char* argv[])
{
srand(time(0));
key_t key;
int shmemaddr;
//shared memory
key=ftok(argv[0],1);
shmemaddr=shmget(key,MEMSIZE,IPC_CREAT|S_IRUSR|S_IWUSR);
sharedmem = shmat(shmemaddr,NULL,0);
pid = fork();
if ( pid > 0 )
{
//timer
struct itimerval timer;
timer.it_value.tv_sec = 3;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 3;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);
signal(SIGALRM, parentHandler1);
signal(SIGUSR1, childHandler);
}
else if ( pid == 0 )
{
signal(SIGUSR2, parentHandler2);
}
//not so busy waiting
while(1) sleep(1);
return 0;
}
https://gist.github.com/4299915
Fork creates a new copy of the current process. Global variables aren't shared between processes. The only memory that is shared between your two processes is the memory returned by shmget. The value of numPassenger is never set in the child process.

Resources