Search code examples
cpipemkfifo

Wait() causing program to pause when opening FIFO named pipe


My code is pausing on open() whenever I use the wait function, and without it the programs dont work. There is no error code but I would like to know whats wrong.

The code will eventually be controller.c will open c1,c2,c3. Where it will wait for c1 which will get input and put it to a pipe which will then go to c2 which will print it, then c3 which will print it in a different format.

int main(int ac, char**av)
{
    int fd;
    int test;
    char * myfifo = "/tmp/myfifo";
    unlink(myfifo);                     //makes sure no fifo already exists

    /* create the FIFO (named pipe) */
    if((mkfifo(myfifo, 0666)) <0)
        perror("MKFIFO: ");



    int statval;
    pid_t pid1 = fork();                    //creates a process for c1 to run in
    wait(&statval); 
    if ( pid1 == 0)                     //makes sure to only run the program in the child process
    {   
        printf("Opening c1\n");
        int x = execvp("./c1",av);          //Runs the other file based on the array
        if (x == -1)
            exit (1);
        perror("Error");                //used for error reporting
        printf("Closing c1\n");
        exit(0);                    //ends process when finished
    }
    if (WIFEXITED(statval))                 //if there is an exit code
    printf("\nChilds exit code %d\n", WEXITSTATUS(statval));//prints the exit status of the child process

    pid_t pid2 = fork();                    //creates a process for c2 to run in
    wait(&statval); 
    if ( pid2 == 0)                     //makes sure to only run the program in the child process
    {   
        printf("Opening c2\n");
        int x = execvp("./c2",av);          //Runs the other file based on the array
        if (x == -1)
            exit (1);
        perror("Error");                //used for error reporting
        exit(0);                    //ends process when finished
    }
    if (WIFEXITED(statval))                 //if there is an exit code
    printf("\nChilds exit code %d\n", WEXITSTATUS(statval));//prints the exit status of the child process

    unlink(myfifo);

C1:

printf("TEST1\n");
    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    int fd;
        char * myfifo = "/tmp/myfifo";
        char buf[BUFSIZE];

    fd = open(myfifo, O_WRONLY);
    if (fd < 0)
        perror("OPEN: ");   

    //while (1) {
        printf("Enter a line of text\n"); 
        //scanf("%s", buf);
        if ((strcmp(line,"-999"))==0){
            printf("TEST");         
            //break;
        }
        //write(fd, buf, sizeof(buf));
            write(fd, "hi", sizeof("hi"));
    //}
    close(fd);
    unlink(myfifo);
        return 0;

C2:

int fd;
    char * myfifo = "/tmp/myfifo";
    char buf[BUFSIZE];

    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);
    read(fd, buf, BUFSIZE);
    printf("Received: %s\n", buf);
    close(fd);

    return 0;

The program will open c1, print TEST and then do nothing else until I manually exit.


Solution

  • Immediately after the first fork, both parent and child wait(). The child's call fails because it has no un-waited-for children, but you ignore the result. The child then execs program c1, which (supposing the exec succeeds) in turn opens the FIFO for writing. This blocks until the other end of the FIFO is opened, but the other end will not be opened by your program because the parent process is waiting for the child to exit before it proceeds. You have created a deadlock.

    Neither child can proceed past opening the FIFO until the other (or some other program) has opened the other end of the FIFO, so the parent must fork both children before it waits for either one. Also, it is pointless for the children to wait(), though their calls to that function should fail quickly.