From: Hiro on
Hello,

I'm trying to test program that generates 3 children, 1st, 2nd, and
3rd,
and force to execute them in reverse order(3rd->2nd->1st), using 2
semaphoes.

However, when I operate against 2 semaphoe at onece using following,
if( semop(sem_bin, sem_buf_v1_p2, 2) == -1){
the program seems to be deadlock.

On the other hand, when I use following instead above, it works as
expected.

if( semop(sem_bin, &sem_buf_both_v[0], 1) == -1){
perror("error to get semaphoe");
exit(-1);
}
if( semop(sem_bin, &sem_buf_both_p[1], 1) == -1){
perror("error to get semaphoe");
exit(-1);
}

But I was thinking both of them are equivalent.
Could someone tell me what's going wrong?


The entire code is following, and I'm working on Ubuntu, and gcc.
Linux HOGE2 2.6.24-23-generic #1 SMP Wed Apr 1 21:47:28 UTC 2009 i686
GNU/Linux


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>



int main(void)
{
int i, sem_bin;
int pid, ret;
int semval;
struct sembuf sem_buf_both_v[2] = {
{
0, // first semaphoe to operate
1, // operation (V)
SEM_UNDO, // if process terminates, automatically
undone
},
{
1, // second semaphoe to operate
1, // operation (V)
SEM_UNDO, // if process terminates, automatically
undone
}
};
struct sembuf sem_buf_both_p[2] = {
{
0, // first semaphoe to operate
-1, // operation (P)
SEM_UNDO, // if process terminates, automatically
undone
},
{
1, // second semaphoe to operate
-1, // operation (P)
SEM_UNDO, // if process terminates, automatically
undone
}
};

/* V to first, then P to second */
struct sembuf sem_buf_v1_p2[2] = {
{
0, // second semaphoe to operate
1, // operation (V)
SEM_UNDO, // if process terminates, automatically
undone
},
{
1, // first semaphoe to operate
-1, // operation (P)
SEM_UNDO, // if process terminates, automatically
undone
},
};
key_t key = time(0);

/*
* get semaphe
* here, allocating 2 semaphoe with one key
*
*/
if( (sem_bin = semget(key, 2, 0666|IPC_CREAT)) < 0 ){
perror("error to get semaphoe");
exit(-1);
}

/* make first child */
pid = fork();
if(pid == 0){
/*
* p operation to first semaphoe
**/
if( semop(sem_bin, &sem_buf_both_p[0], 1) == -1){
perror("error to get semaphoe");
exit(-1);
}

/*
* v operation to first semaphoe
* ( wake up second child )
*
if( semop(sem_bin, &sem_buf_both_v[0], 1) == -1){
perror("error to get semaphoe");
exit(-1);
}
if( semop(sem_bin, &sem_buf_both_p[1], 1) == -1){
perror("error to get semaphoe");
exit(-1);
}
**/
if( semop(sem_bin, sem_buf_v1_p2, 2) == -1){
perror("error to get semaphoe");
exit(-1);
}

pid = getpid();
printf("first child :[%d]\n", pid);
exit(0);

}else if (pid == -1){
perror("fork error");
exit(-1);
}


/* make second child */
pid = fork();
if(pid == 0){
/* child */
if( semop(sem_bin, &sem_buf_both_p[0], 1) == -1){
perror("error to get semaphoe");
exit(-1);
}
pid = getpid();
fprintf(stderr, "second child:[%d]\n", pid);
if( semop(sem_bin, sem_buf_both_v, 2) == -1){
perror("error to get semaphoe");
exit(-1);
}
exit(0);
}else if (pid == -1){
perror("fork error");
exit(-1);
}

/* make third child */
pid = fork();
if(pid == 0){
/* child */
pid = getpid();
printf("third child:[%d]\n", pid);

/* release first semaphoe */
if( semop(sem_bin, sem_buf_both_v, 1) == -1){
perror("error to get semaphoe");
exit(-1);
}
exit(0);
}else if (pid == -1){
perror("fork error");
exit(-1);
}

while(wait(&ret)>=0){
printf("wait!!");
}

/* remove semaphoe */
if( semctl(sem_bin, 0, IPC_RMID) < 0 ){
perror("error to remove semaphoe");
exit(-1);
}
return 0;
}


Thank you
--
Yoshi