tags:

views:

484

answers:

2

I want to make a simple program, that fork, and the child writes into the named pipe and the parent reads and displays from the named pipe. The problem is that it enters the parent, does the first printf and then it gets weird, it doesn't do anything else, does not get to the second printf, it just ways for input in the console.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
char t[100];
mkfifo("myfifo",777);
pid_t pid;
pid = fork();
if (pid==0)
{
    //execl("fifo2","fifo2",(char*)0);
    char r[100];
    printf("scrie2->");
    scanf("%s",r);

    int fp;
    fp = open("myfifo",O_WRONLY);
    write(fp,r,99);
    close(fp);
    printf("exit kid \n");
    exit(0);
} else
{
    wait(0);
    printf("entered parent \n"); // <- this it prints
    // whats below this line apparently its not being executed
    int fz; printf("1"); 
    fz = open("myfifo",O_RDONLY); printf("2");
    printf("fd: %d",fz);
    char p[100];
    int size;
    printf("------");
    //struct stat *info;
    //stat("myfifo",info); printf("%d",(*info).st_size);
    read(fz,p,99);
    close(fz);
    printf("%s",p);

    printf("exit"); exit(0);
}
}
+2  A: 

First of all, try fprintf to stderr instead of printf (to stdout)

The stderr is unbuffered.

Then you can tell what actually gets printed and what does not.

or at least add fflush before waiting for anything.

EFraim
+2  A: 

You really should be checking the return value on function calls for errors, especially mkfifo() and open().

Your call to wait() is going to cause problems in its current location. Opening a FIFO for reading normally blocks until some other process opens the same FIFO for writing, and vice versa1. The parent is waiting for the child to terminate and the child is waiting for a reader process, i.e., the parent, to connect to the FIFO.

1 - see note on open() below for using O_NONBLOCK with a FIFO

Moving the wait() call to just before the parent process exits along with changing the mode in the call to mkfifo() to 0666 seems to resolve some of your immediate problems.

It is also good practice to remove the FIFO when you are finished with it.

unlink("myfifo");

From the open() function documentation in IEEE Std 1003.1-2004:

When opening a FIFO with O_RDONLY or O_WRONLY set:

  • If O_NONBLOCK is set, an open() for reading-only shall return without delay. An open() for writing-only shall return an error if no process currently has the file open for reading.

  • If O_NONBLOCK is clear, an open() for reading-only shall block the calling thread until a thread opens the file for writing. An open() for writing-only shall block the calling thread until a thread opens the file for reading.


The following example is a combination of the code in your original question and the FIFO page of Beej's Guide to Unix IPC:

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

#define FIFO_NAME "myfifo"

int main(void)
{
    char buf[256];
    int num, fd;
    pid_t pid;

    if (mkfifo(FIFO_NAME, 0666) < 0)
        perror("mkfifo");

    pid = fork();
    if (pid == 0)
    {
        printf("child - waiting for readers...\n");
        if ((fd = open(FIFO_NAME, O_WRONLY)) < 0)
            perror("child - open");

        printf("child - got a reader -- type some stuff\n");
        while (fgets(buf, sizeof(buf), stdin), !feof(stdin))
        {
            if ((num = write(fd, buf, strlen(buf))) < 0)
                perror("child - write");
            else
                printf("child - wrote %d bytes\n", num);
        }

        close(fd);
        exit(0);
    }
    else
    {
        printf("parent - waiting for writers...\n");
        if ((fd = open(FIFO_NAME, O_RDONLY)) < 0)
            perror("parent - open");

        printf("parent - got a writer\n");
        do
        {
            if ((num = read(fd, buf, sizeof(buf))) < 0)
                perror("parent - read");
            else
            {
                buf[num] = '\0';
                printf("parent - read %d bytes: \"%s\"\n", num, buf);
            }
        } while (num > 0);

        close(fd);
        wait(0);
    }

    unlink(FIFO_NAME);
    return 0;
}

This example was tested in Linux. Press Ctrl-D to terminate the program.

jschmier
i open the FIFO but i close it in the same process. so it should not block. and i NEED that my parent process to wait after its child, because the child gets input, and i cannot not wait on the first line of the parent because that would mean to begin to read from the fifo, when i dind't even finish to write on it
Blitzkr1eg
now i have:char c[2]; c[1] = 0; c[0]=0;c[0] = strlen(r); // c[0] is lets say 4write(fp,c,1); //fp is the FIFOthen in another process://open pipe, i check for errors, but there are no errors, so it open finechar c[2]; c[1]=0; c[0]=0;read(fz,c,1); //fz is the pipe//and now c[0] is 0 instead of what it should be, 4
Blitzkr1eg
It can be difficult following code changes described in comments. You are better off editing your question to show what you've tried. I've added an example to my response that should help you out.
jschmier
There is also a good [named pipe tutorial](http://developers.sun.com/solaris/articles/named_pipes.html) on the Sun Developer Network that you may find useful.
jschmier