tyler124
tyler124

Reputation: 673

FIFO between multiple processes - Only printing from a single process

I'm trying to make a FIFO between two programs (one being a child process of the other) so that the child can write data back to the parent. Here's what I have so far:

(Parent)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX_BUF 1024

int main(int argc, char *argv[]) {

    //number of seperate processes to create
    int num_processes = 4;
    int i = 0;

    //FIFO accross processes
        int fd;
        char * myfifo = "/tmp/myfifo";
        char buf[MAX_BUF];
        /* create the FIFO (named pipe) */
        mkfifo(myfifo, 0666);

    for (i; i < num_processes; i++) {
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    }
    else if (pid == 0) {
        //child now exec's
        char* args[] = {"./child", "args", NULL};
        execv("./child", args); 
    }
     }

    printf("Parent doing stuff\n");


    //Parent wait for child
    printf("Parent waiting on child\n");



        /* open, read, and display the message from the FIFO */
        fd = open(myfifo, O_RDONLY);
        if (fcntl(fd, F_GETFD) == -1) {
             perror("fd failed");
             exit(1);
        }   
        read(fd, buf, MAX_BUF);
        printf("Received: %s\n", buf);

    //Wait for child processes to finish
    int j = 0;
        for (j; j < num_processes; j++) {
    wait(NULL);
    }
    //Close FIFO
        close(fd);
    return 0;
}

(Child, created 4 times)

void main() {

    printf("Completed\n");

   //Create FIFO
    int fd;
    char * myfifo = "/tmp/myfifo";



    /* write "Hi" to the FIFO */
    fd = open(myfifo, O_WRONLY);
    if (fcntl(fd, F_GETFD) == -1) {
    perror("open failed");
    exit(1);
    }   
    write(fd, "Hi", sizeof("Hi"));
    //close(fd);

    /* remove the FIFO */
    //unlink(myfifo);   
}

Right now, "Completed" is being printed 4 times, showing that there are 4 seperate processes running as there should be. However, only one "Received: Hi" is printed in the terminal. How come I am not getting a FIFO response from the other processes?

Any help would be greatly appreciated!

Upvotes: 0

Views: 1060

Answers (3)

tyler124
tyler124

Reputation: 673

Solved by putting my read statements into the loop waiting for the child processes to finish:

    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);

    if (fcntl(fd, F_GETFD) == -1) {
    perror("fd failed");
    exit(1);
}               


//Wait for child processes to finish
int j = 0;
    for (j; j < num_processes; j++) {
    read(fd, buf, MAX_BUF);
    printf("Received: %s\n", buf);
    wait(NULL);
}
//Close
    close(fd);
return 0;

Upvotes: 0

terence hill
terence hill

Reputation: 3454

The problem in your code is that there are multiple child writing to the same FIFO.

As pointed out also by user3386109 you have to wait each child and read the FIFO. here is a sample code:

   //Wait for child processes to finish
        int child_status = 0;
        while (wait(&child_status) !=  -1) {
                if (WIFEXITED (child_status)) {
                        fprintf (stdout, "the child process exited normally, with exit code %d\n", WEXITSTATUS (child_status));

                        // Read The buffer
                        read(fd, buf, MAX_BUF);
                        printf("Received: %s\n", buf);

                }
                else fprintf (stderr, "the child process exited abnormally\n");
        }

I also suggest to pass to the child an id (this is just a sample add checks if needed):

   else if (pid == 0) {
        //child now exec's
        char mypid[10];
        snprintf(mypid, 10, "%d", i);
        char* args[] = {"./child", mypid, NULL};
        execv("./child", args);
        sleep(1);

That each child read in argv[1]

int mypid = atoi(argv[1]);

Please, see also this post: C Named pipe (fifo). Parent process gets stuck

Upvotes: 0

user3386109
user3386109

Reputation: 34829

You need to check fd and make sure the open succeeded. And note that it can only succeed once, because the first child will unlink(myfifo).

The parent should also wait for all of the children to finish before reading from the fifo. And the parent should read the fifo in a loop until the fifo is empty.

Upvotes: 1

Related Questions