process stuck in waiting - c

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.

Related

Mutex Deadlock (pthread_mutex)

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

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().

Pthread in C basic print

I'm writing a C program using Pthreads that creates a child thread. After creating the child thread, the parent thread should ouput two messages: "parent:begin" then it should print "parent:done". Same for child thread "child:begin" and "child:done". I have to make sure that the main thread prints his second message before the spawned (child) thread does. I have to following implementation but it only prints in the wrong order. I assume I should use flags. Any help would be appreciated.
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
volatile int done = 0;
void *child(void *arg) {
printf("child\n");
done = 1;
printf("child:done");
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t c;
pthread_create(&c, NULL, child, NULL); // create child
while (done == 0); // spin
printf("parent: end\n");
return 0;
}
If you want the parent to print done first, then you should have the child thread spin until the parent is done. (Right now the parent spins waiting for the child.) You should also use pthread_join to make sure the child is done before the main thread returns:
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
volatile int done = 0;
void *child(void *arg) {
printf("child: begin\n");
while (done == 0); // spin
printf("child: done\n");
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t c;
pthread_create(&c, NULL, child, NULL); // create child
printf("parent: done\n");
done = 1;
pthread_join(c, NULL);
return 0;
}
On my machine I get this output:
parent: begin
parent: done
child: begin
child: done
At the moment done is accessed without any synchronization by both threads. Proper way is to signal the child that the parent has completed printing using a conditional variable. This leads to data race.
Moreover, main() thread complete the execution before the does. In that case, the whole process will die. You can either call pthread_join() or simply exit the main thread with pthread_exit().
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
volatile int done = 0;
void *child(void *arg) {
printf("child\n");
pthread_mutex_lock(&mutex);
while(done == 0)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
printf("child:done");
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t c;
pthread_create(&c, NULL, child, NULL); // create child
pthread_mutex_lock(&mutex);
done = 1;
printf("parent: end\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}

Pthread function starting in C

I'm actually new in processes, threads, semaphores, ipc etc(shortly operating system operations on Linux)... My problem is that I compile my code and It simply gets stuck at so funny points. Processes are executed, but they can't enter their threads' function. After that, program directly ends without doing something. I really can't figure out the problem is here or everything have problem. I don't know.
#define _GNU_SOURCE
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void * function1(void *ptr)
{
printf("Function 1\n"); //!Test prints
printf("Index is %d",*((int *)ptr));
sleep(1);
pthread_exit(NULL);
}
void * function2(void *ptr)
{
printf("Function 2\n"); //!Test prints
printf("Index is %d",*((int *)ptr));
sleep(2);
pthread_exit(NULL);
}
int main(){
//...
int *index;
int i;
pid_t f;
int number_of_process=5;
pthread_t thread1, thread2;
//...
for(i=0; i<number_of_process; i++)
{
f=fork();
if(f==-1)
{
printf("Fork Error!!\n");
exit(1);
}
if(f==0) //To block child processes re-enter
{
*index = i; //I store index number for each process here. I'll need them in the thread functions
break;
}
}
/*******************PARENT PROCESS********************/
if(f!=0){
// wait for all children to exit
while (f = waitpid (-1, NULL, 0)){
if (errno == ECHILD)
break;
}
exit(0);
}
/*******************CHILD PROCESS*********************/
else{
pthread_create(&thread1,NULL,function1,(void *)index);
pthread_create(&thread2,NULL,function2,(void *)index);
}
}
Processes are executed, but they can't enter their threads' function.
After that, program directly ends without doing something.
That's because the main thread (i.e. child process created by fork()) doesn't wait for the threads to complete their execution. So it gives you the impression that the program exits without calling all pthread functions.
Use pthread_join() after creating threads:
...
pthread_create(&thread1,NULL,function1,(void *)index);
pthread_create(&thread2,NULL,function2,(void *)index);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
...
The output may be interleaved due to threads printing without any synchronization.

parent doesn't create child?

I try to create 4 child processes who will work simultaneously, but the output of my program is quite random: sometimes one of the processes is not created (the printf statement is not executed). I can not understand the reason for this, because when I use the wait() function in my parent it should wait for it's children to finish? Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define NR_OF_PROCESSES 4
void readProcess(void);
void tokenProcess(void);
void calculatorProcess(void);
void errorProcess(void);
void (*functionTable[NR_OF_PROCESSES]) (void) = {readProcess, tokenProcess, calculatorProcess, errorProcess};
int main(void) {
int i;
int status;
for (i = 0; i < NR_OF_PROCESSES; i++) {
int pid = fork();
if (pid < 0) {
perror("could not fork");
return 0;
}
if (pid == 0) {
functionTable[i]();
exit(0);
}
}
printf("parent is waiting");
wait(status);
return (0);
}
void readProcess(void) {
printf("readprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
void tokenProcess(void) {
printf("tokenprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
void calculatorProcess(void) {
printf("calculatorprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
void errorProcess(void) {
printf("errorprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
Also, I want to add interprocess communication with pipes later on. Will this be possible if I implement the processes this way? Any better solution?
You only wait for one child, you probably want to call wait for each child.

Resources