Martin Komara
Martin Komara

Reputation: 41

semaphores + pthreads, not working properly

I have this graph of process. In every thread new process begin. First is process 1, when it ends semaphores are posted and next possible process are 2 and 4.
This graph explain more : 1: http://i49.tinypic.com/34t5uo0.png .My script crashes in some times. Process 1,2, or 4 do not execute. Where is a problem ?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h> 




sem_t semA,semB,semC,semD,semE;


void* process_2 (void* param)
{ 
  sem_wait(&semA);
  int pid2, status2; 
  pid2 = fork ();
  if ( pid2 < 0 ) {
   exit(1);
  }
 if ( pid2==0 ) { 

  printf("Process 2\n");
  }
 else {
  wait(&status2);
  sem_post(&semC);
 } 
 return NULL;
}

void* process_4(void* param)
{   
 sem_wait(&semB);
 int pid4, status4;
 pid4 = fork ();
 if ( pid4 < 0 ) {
  exit(1);
 }
 if ( pid4==0 ) { 

   printf("Process 4\n");


  exit(0);
 }
 else {
  wait(&status4);
  sem_post(&semD);                          
 }


 return NULL;
}


void* process_3(void* param)
{
 sem_wait(&semC);
 int pid3, status3;
 pid3 = fork();
  if (pid3 < 0) {
  exit(0);
 }
 if (pid3 == 0) {  

   printf("Process 3\n");
 }
 else{
  wait(&status3);
  sem_post(&semE);
 }

 return NULL;

}

void* process_5(void* param)
{
 sem_wait(&semD);
 sem_wait(&semE);
 int pid5, status5;
 pid5 = fork();
 if (pid5 < 0) {
   exit(0);
 }
 if (pid5 == 0) {  
  printf("Process 5\n");
 }
 else{
  wait(&status5);
  exit(0);
 }

 return NULL;

}



int main () {

  pthread_t thread_id[4];
  pthread_create(&thread_id[0], NULL,&process_2, NULL);
  pthread_create(&thread_id[1], NULL,&process_3, NULL);
  pthread_create(&thread_id[2], NULL,&process_4, NULL);
  pthread_create(&thread_id[3], NULL,&process_5, NULL);


  sem_init(&semA,0,0); 
  sem_init(&semB,0,0);
  sem_init(&semC,0,0);
  sem_init(&semD,0,0);
  sem_init(&semE,0,0);


  int pid, status;


  pid = fork ();
  if ( pid < 0 ) {
   exit(1);
   }
  if ( pid==0 ) {  
   printf("Process 1\n");    
   }
  else { 
   wait(&status);
   sem_post(&semA);
   sem_post(&semB);
   int i;
   for (i = 0; i < 4; i++)
    pthread_join(thread_id[i],NULL);   
   return 0;
   }
 exit(0);

} 

Upvotes: 2

Views: 1716

Answers (2)

Jens Gustedt
Jens Gustedt

Reputation: 78903

Ben's answer shows you your main problem, but you have others. You are taking programming with threads, processes and semaphores much to easy.

  • Semaphores are not to be programmed like this. All the semaphore functions give error return codes for a good reason. E.g sem_wait may encouter "spurious wakeups" if the process receives a signal. So you'd have to check the return and then errno to see what happened, there is no way around this when programming POSIX semaphores.

  • Semaphores are only an optional feature in POSIX. It is probably easier to start with the POSIX features that were designed into it from the beginning, namely pthread_mutex_t and pthread_cond_t. What you obtain as a supplement is portability. There are still very common architectures around that don't fully support semaphores.

  • The way your are doing this is not the way to share semaphores between processes:

    The entire virtual address space of the parent is replicated in the child

    which means that the semaphore in the child is a copy, and the two processes will not be able to communicate through it. You'd have to use something like shm_open and mmap create process shared semaphores.

  • Mixing fork and threads is usually not a trivial task and you should really think twice before doing that.

Upvotes: 2

Ben Kelly
Ben Kelly

Reputation: 1344

At least one problem is you spawn the threads before initializing the semaphores:

pthread_t thread_id[4];
pthread_create(&thread_id[0], NULL,&process_2, NULL);
pthread_create(&thread_id[1], NULL,&process_3, NULL);
pthread_create(&thread_id[2], NULL,&process_4, NULL);
pthread_create(&thread_id[3], NULL,&process_5, NULL);


sem_init(&semA,0,0); 
sem_init(&semB,0,0);
sem_init(&semC,0,0);
sem_init(&semD,0,0);
sem_init(&semE,0,0);

This creates a race condition between the main thread initializing the semaphores and the child threads using them. There is a really good chance of using uninitialized data here.

I recommend swapping the order in your main() function:

pthread_t thread_id[4];

sem_init(&semA,0,0); 
sem_init(&semB,0,0);
sem_init(&semC,0,0);
sem_init(&semD,0,0);
sem_init(&semE,0,0);

pthread_create(&thread_id[0], NULL,&process_2, NULL);
pthread_create(&thread_id[1], NULL,&process_3, NULL);
pthread_create(&thread_id[2], NULL,&process_4, NULL);
pthread_create(&thread_id[3], NULL,&process_5, NULL);

Upvotes: 3

Related Questions