My code forks n processes. When the last process is reached, it sends a message to the top level process via a FIFO to kill all processes. My code works great, except the the last process never reaches my signal and never gets killed by the top process.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/signal.h>
#include <unistd.h>
#include <errno.h>
#include <stdbool.h>
#define MAX_BUF 1024
int *ptr;
int numprocs;
void signal_handler(int sig){
int currpid = getpid();
int lev;
int i;
for(i = 1; i < numprocs; i++){
if(ptr[i] == currpid){
lev = numprocs - i;
break;
}
}
fprintf(stdout,"EXITING: Level %d process with pid=%d, child of ppid=%d.\n", lev, ptr[i], ptr[i-1]);
exit(0);
}
int main(int argc, char **argv){
numprocs = atoi(argv[1]);
int lev = numprocs;
bool x = true;
//create shared memory
const int SIZE = numprocs * sizeof(int);
const char *name = "dleggio1OS";
int shm_fd;
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, SIZE);
ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
*ptr = getpid();
//create unnamed pipe
int pfds[2];
char buf[30];
if(pipe(pfds) == -1){
perror("pipe");
exit(1);
}
//create fifo
int fd;
char *myfifo = "/tmp/dleggio1fifo";
mkfifo(myfifo, 0666);
pid_t pid = fork();
if(pid == 0){ //first child ..... keep forking
//read unnamed pipe
close(pfds[1]);
if(read(pfds[0], buf, 3) <= 0){
perror("child");
exit(1);
}
int check = atoi(buf);
fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", check, getpid(), getppid());
//write to shared memory
ptr[numprocs - check] = getpid();
signal(SIGUSR1,signal_handler);
int i;
lev--;
for(i = 2; i < numprocs; i++){
//create named pipe
int pfds[2];
char buf[30];
if(pipe(pfds) == -1){
perror("pipe");
exit(1);
}
lev--;
pid_t pid;
if((pid = fork()) < 0){
perror("fork");
exit(1);
}
else if(pid == 0){
//update shared memory
ptr[i] = getpid();
//read from named pipe
close(pfds[1]);
if(read(pfds[0], buf, 3) <= 0){
perror("child");
exit(1);
}
int check = atoi(buf);
fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", check, getpid(), getppid());
if(check == 1){
//write to fifo
fd = open(myfifo, O_WRONLY);
write(fd,"leaf",sizeof("leaf"));
close(fd);
unlink(myfifo);
signal(SIGUSR1,signal_handler);
}
signal(SIGUSR1,signal_handler);
}
else{
//write to named pipe
close(pfds[0]);
char hold[3];
sprintf(hold,"%d",lev);
if(write(pfds[1], hold, 3) <= 0){
perror("parent");
exit(1);
}
wait(NULL);
}
}
}
else{ //top level
fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", lev, getpid(), getppid());
//write to unnamed pipe
lev--;
close(pfds[0]);
char hold[3];
sprintf(hold,"%d",lev);
if(write(pfds[1], hold, 3) <= 0){
perror("parent");
exit(1);
}
//read from fifo
char buff[MAX_BUF];
fd = open(myfifo,O_RDONLY);
read(fd,buff,MAX_BUF);
close(fd);
unlink(myfifo);
char *comp = "leaf";
if(strcmp(buff,comp) == 0){
int j;
for(j = 0; j < numprocs; j++) printf("%d\n",ptr[j]);
for(j = 1; j < numprocs; j++) kill(ptr[j],SIGUSR1);
shm_unlink(name);
fprintf(stdout,"EXITING: Level %d process with pid=%d, child of ppid=%d.\n", numprocs, getpid(), getppid());
exit(0);
}
}
}
Output:
./prog1 4
ALIVE: Level 4 process with pid=5129, child of ppid=4692.
ALIVE: Level 3 process with pid=5130, child of ppid=5129.
ALIVE: Level 2 process with pid=5131, child of ppid=5130.
ALIVE: Level 1 process with pid=5132, child of ppid=5131.
5129
5130
5131
5132
EXITING: Level 4 process with pid=5129, child of ppid=4692.
EXITING: Level 3 process with pid=5130, child of ppid=5129.
EXITING: Level 2 process with pid=5131, child of ppid=5130.
Related
I write a program containing two processes: the first one contains a group of two semaphores and creates the child process that reads all data in the shared memory segment and prints them.
In the second one, the child process computes the data using a compute function that returns 0 when all data are computed. It transmits them to the parent through the shared memory segment.
To write data:
On the 1st semaphore the child makes P and the parent make V.
On the 2nd semaphore the child makes V and the parent make P.
But as I'm new in this topic and still getting hardness to understand, it seems like I'm doing something wrong because it's not working as it has to be.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>
int sum =0;
int compute(int data){
sum += data;
return sum;
}
int main(){
int i;
int shm_id;
int data;
pid_t pid;
key_t shm_key;
sem_t *sem;
// unsigned int sem_value =2;
shm_key = ftok("/dev/null", 65);
shm_id = shmget(shm_id, sizeof(int), 0644 | IPC_CREAT);
if (shm_id < 0){
perror("shmgget");
exit(EXIT_FAILURE);
}
// data = shmat(shm_id, NULL, 0);
sem = sem_open("semaphore", O_CREAT | O_EXCL, 0644, 2);
for (i = 0; i < 2; i++){
pid = fork();
if (pid < 0)
{
perror("fork");
sem_unlink("semaphore");
sem_close(sem);
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
break;
}
}
if (pid == 0)
{
puts("Enter the data:");
scanf("%d", &data);
//child process
sem_wait(sem);
printf("Child - %d is in critical section\n", i);
sleep(1);
puts("Enter the data:");
scanf("%d", &data);
// *shrd_value += data;
printf("Child - %d: new value of data = %d\n", i, data);
printf("Child - %d: sum of whole data by far = %d\n", i, compute(data));
sem_post(sem);
exit(EXIT_SUCCESS);
}
else if (pid > 0)
{
//parent process
while (pid = waitpid(-1, NULL, 0))
{
if (errno == ECHILD)
{
break;
}
}
puts("All children exited");
shmdt(&data);
shmctl(shm_id, IPC_RMID, 0);
sem_unlink("semaphore");
sem_close(sem);
exit(0);
}
}
Output:
Enter the data:
Enter the data:
2
Child - 0 is in critical section
1Enter the data:
Child - 1 is in critical section
Enter the data:
3
Child - 0: new value of data = 3
Child - 0: sum of whole data by far = 3
2
Child - 1: new value of data = 2
Child - 1: sum of whole data by far = 2
All children exited
I have also modified the way they write to shared memory: they write directly at the address given by shmat call that is missing in your code.
I have fixed some bugs and simplifed the code (removed the array - added detailed logging especially before and after entering the critial section):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>
int main(){
int i;
int shm_id;
pid_t pid;
int *addr;
int data;
pid_t current_pid;
key_t shm_key;
sem_t *sem;
shm_key = ftok("/dev/null", 65);
shm_id = shmget(shm_key, sizeof(int), 0644 | IPC_CREAT);
if (shm_id < 0){
perror("shmget");
exit(EXIT_FAILURE);
}
sem_unlink("semaphore");
sem = sem_open("semaphore", O_CREAT, 0644, 1);
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
addr = (int *) shmat(shm_id, (void *) 0, 0);
if (addr == (void *) -1) {
perror("shmat");
exit(EXIT_FAILURE);
}
*addr = 0;
for (i = 0; i < 2; i++){
pid = fork();
if (pid < 0)
{
perror("fork");
sem_close(sem);
sem_unlink("semaphore");
exit(EXIT_FAILURE);
}
}
if (pid == 0)
{
current_pid = getpid();
printf("Child %d: waiting for critical section \n", current_pid);
sem_wait(sem);
printf("Child %d: enters in critical section \n", current_pid);
printf("child %d: Enter the data:\n", current_pid);
scanf("%d", &data);
printf("Child %d: new value of data = %d\n", current_pid, data);
printf("Child %d: sum of whole data so far = %d\n", current_pid, *addr += data);
sem_post(sem);
printf("Child %d exits from critical section\n", current_pid);
exit(EXIT_SUCCESS);
}
else if (pid > 0)
{
//parent process
while (pid = waitpid(-1, NULL, 0))
{
if (errno == ECHILD)
{
break;
}
}
puts("All children exited");
shmdt(addr);
shmctl(shm_id, IPC_RMID, 0);
sem_close(sem);
sem_unlink("semaphore");
exit(0);
}
exit(0);
}
Note that semaphore initial value must be 1 to have a true critical section for 2 processes.
I have also removed the sleep calls and we can see that one of the process is waiting:
Child 22514: waiting for critical section
Child 22514: enters in critical section
child 22514: Enter the data:
Child 22515: waiting for critical section
333
Child 22514: new value of data = 333
Child 22514: sum of whole data so far = 333
Child 22514 exits from critical section
Child 22515: enters in critical section
child 22515: Enter the data:
666
Child 22515: new value of data = 666
Child 22515: sum of whole data so far = 999
Child 22515 exits from critical section
All children exited
All children exited
Here's the code with producer and consumer process
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> // O_CREAT, O_EXEC
#include <errno.h> // errno, ECHILD
#include <unistd.h>
#include <sys/shm.h> // shmat(), IPC_RMID
#include <sys/wait.h>
#include <semaphore.h> // sem_open(), sem_destroy(), sem_wait()...
#include <sys/types.h> // key_t, sem_t, pid_t
#include <pthread.h>
#define BUFF 10
typedef struct data{
int buff[BUFF];
int size;
int index;
}DATA;
int main(int argc, char const *argv[])
{
sem_t *full, *empty, *access;
key_t shm_key;
int shm_id;
full = sem_open ("fullname", O_CREAT , 0644, 15);
empty = sem_open ("empty", O_CREAT , 0644, 0);
access = sem_open ("access", O_CREAT , 0644, 1);
if (argc!=2)
{
exit(1);
}
int value=atoi(argv[1]);
//initialize a shared variable in shared memory
shm_key = ftok("/dev/null", 60);
shm_id = shmget(shm_key, sizeof(DATA), 0);
// shared memory error check
if (shm_id < 0){
shm_id = shmget(shm_key, sizeof(DATA), 0644 | IPC_CREAT);
DATA *data = (DATA*) shmat (shm_id, NULL, 0);
data->size=0;
data->index=0; //index
}
printf("Shared memory id: %d\n",shm_id );
printf("Checking buffer...,\n");
//If in the buffer have free space then will wait for consumer to consume the data\n"
sem_wait(empty);
printf("\nLocking buffer to produce data\n");
sem_wait(access);
//initialize a shared variable in shared memory
shm_key = ftok("/dev/null", 60);
shm_id = shmget(shm_id, sizeof(DATA), 0644 | IPC_CREAT);
// shared memory error check
if (shm_id < 0){
perror("semaphore");
exit(EXIT_FAILURE);
}
//Shared variable
DATA *data = (DATA*) shmat (shm_id, NULL, 0);
int index=(data->size + data->index) % 15;
data->buff[index]=value;
data->size++;
printf("%d is located in %d on the buffer\n",value,index );
//consusming
// attach data to shared memory
index=data->index;
value=data->buff[index];
printf("%d now consumed\n",value );
data->size--;
data->index++;
sem_post(access);
sem_post(full);
return 0;
}
I was wondering if someone can help me modify my current code....
Currently it creates my process using fork() and takes a pointer to a function which executes that childs code block.
I wanted to play around with pipes and attempt to now have Process Y send its pid to Process X and then i want to send it back to the Main...
Heres what i have currently
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h> // exit
#include <fcntl.h>
#include <sys/wait.h>
void processX();
void processY();
pid_t addChild(void (*childPtr) (), int fileDes[2]) {
pid_t cpid;
if((cpid=fork()) == 0) {
pipe(fileDes);
childPtr(fileDes);
wait(NULL);
exit(0);
} else if (cpid < 0) {
printf("failed to fork");
exit(1);
} else {
}
return cpid;
}
void processY(int fileDes[2]) {
printf("Child Y[%d] Created of Parent X[%d]\n", getpid(), getppid());
printf("We are now going to write Y PID to process X\n");
pid_t a = getpid();
char buf[1024]; // child reads from pipe() to buffer
close(fileDes[0]); // close reading end of the pipe
write(fileDes[1], &a, sizeof(buf) / sizeof(int));
}
void processX(int fileDes[2]) {
printf("Child X[%d] Created of parent Main[%d]\n", getpid(), getppid());
int status;
pid_t Y = addChild(processY, fileDes);
wait(&status);
pid_t new_val = 5;
close(fileDes[1]); // closing the writing end of the pipe.
read(fileDes[0], &new_val, sizeof(new_val));
printf("Message read with number %d: \n", new_val);
}
int main() {
int status;
int fd[2];
printf("Main process[%d]\n", getpid());
pid_t root = addChild(processX, fd);
wait(&status);
printf("We are going to read from X to Main and then return the Value we got from Y\n");
return 0;
}
I dont know to create a pipe from Y - X and then X - Main....
Y---->send pid ----> X received Y pid ----- send new info to main --->Main print received data...
My answer i came up with
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h> // exit
#include <fcntl.h>
#include <sys/wait.h>
void processX();
void processY();
pid_t addChild(void (*childPtr) (), int fileDes[2], int backToMainFd[2]) {
pid_t cpid;
if(childPtr != *processX //prevents the the pipe from main to x from recreating
pipe(fileDes);
if((cpid=fork()) == 0) {
if(childPtr == *processX) {
childPtr(fileDes, backToMainFd);
} else {
childPtr(fileDes);
}
wait(NULL);
exit(0);
} else if (cpid < 0) {
printf("failed to fork");
exit(1);
} else {
}
return cpid;
}
void processY(int fileDes[2]) {
printf("[PROCESS Y]: Child Y[%d] Created of Parent X[%d]\n", getpid(), getppid());
pid_t a = getpid();
char buf[1024]; // child reads from pipe() to buffer
close(fileDes[0]); // close reading end of the pipe
write(fileDes[1], &a, sizeof(buf) / sizeof(int));
}
void processX(int fileDes[2], int BackToMainFd[2]) {
printf("[PROCESS X]: Child X[%d] Created of parent Main[%d]\n", getpid(), getppid());
int status;
pid_t Y = addChild(processY, fileDes, NULL);
wait(&status);
pid_t new_val = 5;
close(fileDes[1]); // closing the writing end of the pipe.
read(fileDes[0], &new_val, sizeof(new_val));
printf("[PROCESS X]: We got Ys' PID as:%d from [PROCESS Y]\n", new_val);
close(BackToMainFd[0]); // close reading end of the pipe
char buf[1024]; // child reads from pipe() to buffer
write(BackToMainFd[1], &new_val, sizeof(buf) / sizeof(pid_t));
}
int main() {
int status;
int fd[2];
int backToMainFD[2];
printf("Main process[%d]\n", getpid());
pipe(backToMainFD);
pid_t root = addChild(processX, fd, backToMainFD);
wait(&status);
pid_t new_val = 5;
close(backToMainFD[1]); // closing the writing end of the pipe.
read(backToMainFD[0], &new_val, sizeof(new_val));
printf("[MAIN]: We got Ys' PID as:%d from [PROCESS X]\n", new_val);
printf("Send sig kills too Y and root\n");
kill(new_val, SIGKILL);
kill(root, SIGKILL);
printf("Terminate program.\n");
return 0;
}
So I need this program which needs to create argv[1] child using fork() and print what children number are they and what PID do they have in order of its creation.
I have to do that using pipes blocking properties.
Example output:
I am child 1 and my PID is 25853.
I am child 2 and my PID is 25854.
I am child 3 and my PID is 25855.
This is what I have tried so far, but it doesn't respect the order of children creation.
int main(int argc, char* argv[])
{
char buffer[80];
int p[2], i;
int pid = getpid();
for (i = 0; i < atoi(argv[1]); i++) {
pipe(p);
if (fork() == 0) {
read(p[0], &pid, sizeof(pid)); // It should block here until there's
// something in the pipe to read
sprintf(buffer, "I am child %d and my PID is %d\n", i + 1, getpid());
write(1, &buffer, strlen(buffer));
close(p[0]);
close(p[1]);
exit(0);
}
else { // parent
close(p[0]);
write(p[1], &pid, sizeof(pid));
close(p[1]); // The child is able to read the EOF now.
}
}
while ((waitpid(-1, NULL, 0)) > 0)
;
close(p[0]);
close(p[1]);
sprintf(buffer, "I've finished\n");
write(1, &buffer, strlen(buffer));
}
I feel like I am close but I am not using the pipes block poperties correctly.
I need some advice, thanks.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
if (argc != 2) {
return 1;
}
int const n = atoi(argv[1]);
for (int i = 0; i < n; i++) {
int p[2];
if (pipe(p) != 0)
return 1;
int pid = fork();
if (pid == 0) {
close(p[1]);
if (read(p[0], &pid, sizeof pid) != sizeof pid)
return 1;
close(p[0]);
fprintf(stdout, "I am child %d and my PID is %d\n", i + 1, pid);
return 0;
}
else if (pid > 0) {
close(p[0]);
if (write(p[1], &pid, sizeof pid) != sizeof pid)
return 1;
close(p[1]);
if (waitpid(pid, NULL, 0) == -1)
return 1;
}
else {
return 1;
}
}
fprintf(stdout, "I've finished\n");
}
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv) {
int childs[3];
for (int i = 0; i < 3; ++i) {
int p[2];
if (pipe(p) == -1) { perror("pipe"); exit(1); }
pid_t pid = fork();
if (pid) {
close(p[0]);
childs[i] = p[1];
}
else {
close(p[1]);
printf("child %d start\n", i + 1);
char buf[10];
buf[0] = 0;
int r;
if ((r = read(p[0], buf, 9)) == -1) { ... }
printf("child %d read %s (%d), finish\n", i + 1, buf, r);
sleep(2);
exit(0);
}
}
for (int i = 0; i < 3; ++i) {
// if (argc > 1) {
// write(childs[i], "42", 2);
// }
// ============== HERE >>>
close(childs[i]);
}
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0) {
printf("child %d exited\n", pid);
}
return 0;
}
Output with comment:
child 1 start
child 2 start
child 3 start
child 3 read (0), finish
The next line is displayed after 2 seconds
child 2 read (0), finish
The next line is displayed after 2 seconds
child 1 read (0), finish
I do not write to the channel in the parent. Closing it, I want to give a signal to the child that will be waiting in the read.
It seems that there is a following. Сhild N expected finishes reading from the result 0, it's ok. Children 2 (N-1) and 1 are locked in a read to a child 3 is completed. Then the child 1 is similar will wait.
Why lock occur?
Child processes inherit open file descriptors from their parent. Your main process opens file descriptors in a loop (using pipe, keeping only the write ends). Child 1 inherits no descriptors (except for stdin/stdout/stderr); child 2 inherits childs[0] (the descriptor going to child 1); child 3 inherits childs[0] and childs[1] (the descriptors going to child 1 and 2).
read on a pipe blocks as long as any write descriptor is still open (because it could be used to send more data). So child 1 waits (because child 2 and child 3 still have an open write descriptor) and child 2 waits (because child 3 still has an open write descriptor); only child 3 sleeps and exits. This causes its file descriptors to close, which wakes up child 2. Then child 2 sleeps and exits, closing its file descriptors, which finally wakes up child 1.
If you want to avoid this behavior, you have to close the open file descriptors in each child:
else {
for (int j = 0; j < i; j++) {
close(childs[j]);
}
close(p[1]);
printf("child %d start\n", i + 1);
The write ends of the pipes are getting inherited by the children.
Since filedescriptor are ref-counted, the write end is only considered closed if all references to it are closed.
Below is your code, slightly refactored, with a fix added:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv) {
int children_w[3];
for (int i = 0; i < 3; ++i) {
int p[2];
if (0>pipe(p))
{ perror("pipe"); exit(1); }
pid_t pid;
if(0> (pid= fork()))
{ perror("fork"); exit(1); }
if(pid==0) {
/* Fix -- close the leaked write ends */
int j;
for(j=0; j<i; j++)
close(children_w[j]);
/* end fix*/
close(p[1]);
printf("child %d start\n", i + 1);
char buf[10];
buf[0] = 0;
int r;
if ((r = read(p[0], buf, 9)) == -1) { perror("read");/*...*/ }
printf("child %d read %s (%d), finish\n", i + 1, buf, r);
sleep(2);
exit(0);
}
children_w[i] = p[1];
close(p[0]);
}
for (int i = 0; i < 3; ++i) {
// if (argc > 1) {
// write(childs[i], "42", 2);
// }
// ============== HERE >>>
close(children_w[i]);
}
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0) {
printf("child %d exited\n", pid);
}
return 0;
}
I'm trying to write to a named pipe from a bottom level leaf process and read from the pipe on the top level process.
To do this, I'm first creating the FIFO in the top level process, then using a for loop to fork more processes. In the for loop I'm checking for leaf processes and if it's a leaf, I'm writing to the FIFO and breaking from the loop. Then, after the loop, I'm trying to read from the FIFO in the top level process. This isn't working, my program just gets stuck and stalls after the leaf process is created.
How can I send a message from a leaf back up to the top parent process through a FIFO?
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#define MAX_BUF 1024
int main(int argc, char **argv){
int numprocs = atoi(argv[1]);
int lev = numprocs;
fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", lev, getpid(), getppid());
//create shared memory
const int SIZE = numprocs * sizeof(int);
const char *name = "dleggio1OS";
int shm_fd;
int *ptr;
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, SIZE);
ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
*ptr = getpid();
//create fifo
int fd;
char *myfifo = "/tmp/dleggio1fifo";
mkfifo(myfifo, 0666);
//spawn procs
int i;
for(i = 1; i < numprocs; i++){
lev--;
int pfds[2];
char buf[30];
if(pipe(pfds) == -1){
perror("pipe");
exit(1);
}
pid_t pid;
if((pid = fork()) < 0){
perror("fork");
exit(1);
}
if(pid == 0){ //child
const int SIZE = numprocs * sizeof(int);
const char *name = "dleggio1OS";
int shm_fd;
int *ptr;
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, SIZE);
ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
ptr[i] = getpid();
close(pfds[1]);
if(read(pfds[0], buf, 3) <= 0){
perror("child");
exit(1);
}
int check = atoi(buf);
fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", check, getpid(), getppid());
if(check == 1){ //leaf
fd = open(myfifo, O_WRONLY);
write(fd,"leaf",sizeof("leaf"));
close(fd);
break;
}
}
else{ //parent
close(pfds[0]);
char hold[3];
sprintf(hold,"%d",lev);
if(write(pfds[1], hold, 3) <= 0){
perror("parent");
exit(1);
}
wait(NULL);
return 0;
}
}
//read fifo
char buff[MAX_BUF];
fd = open(myfifo,O_RDONLY);
read(fd,buff,MAX_BUF);
close(fd);
shm_unlink(name);
unlink(myfifo);
return 0;
}
OUTPUT:
ALIVE: Level 3 process with pid=554, child of ppid=451.
ALIVE: Level 2 process with pid=555, child of ppid=554.
ALIVE: Level 1 process with pid=556, child of ppid=555.
_ // <---- stalls here
All processes are hung on a "wait()" call (i.e. waiting for one of its children to exit), except for the last child forked... which is hung on "open(myfifo, O_WRONLY)"....
The last child will continue to hang until a process opens the fifo for reading...