Reputation: 41
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
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.
fork
and threads is usually not a trivial task and you
should really think twice before doing that.Upvotes: 2
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