LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Problems with FIFO pipe using a child and parent process (https://www.linuxquestions.org/questions/programming-9/problems-with-fifo-pipe-using-a-child-and-parent-process-845563/)

mashhype 11-20-2010 08:40 PM

Problems with FIFO pipe using a child and parent process
 
Hi,

I am trying to write a simple program where my parent writes a small message like "hello" to the child. So the parent writes and the child reads. When I run, I get 'child read from fifo failed: resource temporarily unavailable.'

Can someone look at my code and tell me whats wrong or missing? I cant seem to figure it out.

It seems like what is happening is that the parent isnt opening the FIFO to write into it, but why??

Thanks so much!!

Code:

/* Named pipe pipe1.c */
/* Usage: pipe1 pipename. Child reads a message from parent */

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

# define BUFSIZE 256

void main(int argc, char *argv[])
{
mode_t fifo_mode = S_IRUSR | S_IWUSR;
int fd, status;
char buf[BUFSIZE];
unsigned strsize;

if (argc !=2) {
        printf ("\n Usage: %s pipename\n", argv[0]);
        exit(1);
        }
/* generate a named pipe with r/w for user */

if ((mkfifo(argv[1],fifo_mode) == -1) && (errno != EEXIST)) {
        perror ("Pipe");
        exit(1);
        }

switch (fork()) {
case -1:
        perror ("Fork");
        exit(1);
case  0:
               
        printf ("\n Child %ld is about to open FIFO %s\n", (long)getpid(), argv[1]);

        if ((fd = open(argv[1], O_RDONLY | O_NONBLOCK )) == -1)
        {
                perror("child cannot open FIFO");
                exit(1);
        }
        printf ("Child is about to read\n", (long)getpid());
        if (read(fd, buf, BUFSIZE) <=0)
        {
                perror("Child read from FIFO failed\n");
                exit(1);
        }
        printf ("Child %ld received: %s\n", (long)getpid(), buf);
default:
        /* parent does a write */
        printf ("Parent %ld is about to open FIFO %s\n", (long) getpid(), argv[1]);

        if ((fd = open(argv[1], O_WRONLY )) == -1)
        {
                perror("Parent cannot open FIFO");
                exit(1);
        }
        sprintf (buf, "This was written by Parent %ld\n", (long)getpid());
        strsize = strlen(buf) + 1;

        while ((wait(&status) == -1) && (errno == EINTR));
                if (write(fd, buf, strsize) != strsize)
                {
                printf("Parent write to FIFO failed\n");
                exit(1);
                }
        printf ("Parent %ld is done\n", (long)getpid());
}
exit(0);
}


paulsm4 11-21-2010 01:52 AM

Off the top of my head ... don't you WANT the child to block until there's something to read?

mac.tieu 11-21-2010 07:11 PM

You should write to pipe before waiting for client exit. Like this:
Code:

if (write(fd, buf, strsize) != strsize)
{
  printf("Parent write to FIFO failed\n");
  exit(1);
}
while ((wait(&status) == -1) && (errno == EINTR));

Regards,
MT.

paulsm4 11-22-2010 01:00 AM

Nonsense. You don't need a "wait()", nor do you need a busy loop if you've forked() the child and you're using a "mkfifo()" queue.

You SHOULD eliminate the "O_NONBLOCK" in your child:
Code:

  if ((fd = open(argv[1], O_RDONLY)) == -1)
    ... error handing ...
  if (read(fd, buf, BUFSIZE) <=0)
    ... error handling ...

Specifically:
Quote:

http://developerweb.net/viewtopic.php?id=5792

"Resource temporarily unavailable" is EAGAIN, aka EWOULDBLOCK... You will get it
only on file descriptors that you have explicitly set to non-blocking I/O mode... And, it
indicates that your I/O operation would normally have blocked at that point, because
it couldn't occur immediately... (Ie: for reading, there's currently no data to read; for
writing, the buffer is full and needs to be emptied first...)

mashhype 11-22-2010 01:48 AM

Got to work, dont know what I changed but here is the updated code
 
I think the O_NONBLOCK was screwing things up..I still dont understand what that does...but when I took it out, it did what it was supposed to do...I took out the wait(&status) function as well...why did that fix my problem..anyone know?

Here is the final code:
Code:

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

# define BUFSIZE 100

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

mode_t fifo_mode = S_IRUSR | S_IWUSR;
int fd, status, child;
char buf[BUFSIZE];
unsigned strsize;

if (argc !=2) {
        printf ("\n Usage: %s pipename\n", argv[0]);
        exit(1);
        }

if ((mkfifo(argv[1]), fifo_mode) == -1) && (errno != EEXIST)){
        perror("Pipe");
        exit(1);
}

if (( child = fork()) == -1){
        perror("Fork");
        exit(1);
}

else if (child == 0){
        printf("\nChild %ld is about to open FIFO %s\n", (long)getpid(), argv[1]);
       
        if ((fd = open(argv[1], O_RDONLY )) == -1){
                perror("Child cannot open FIFO");
                exit(1);
        }
        printf("Child is about to read\n", (long)getpid());
        //sleep(1);

        if (read(fd, buf, BUFSIZ) <= 0){
                perror("Child read from FIFO failed\n");
                exit(1);
        }
        printf("\nChild %ld received: %s\n", (long)getpid(), buf);
}
else {
        printf("\nParent %ld is about to open FIFO %s\n", (long)getpid(), argv[1]);
       
        if((fd = open(argv[1], O_WRONLY)) == -1){
                perror("Parent cannot open FIFO");
                exit(1);
        }
        /*in the parent*/
        sprintf(buf, "This was written by parent %ld\n", (long)getpid());
        strsize = strlen(buf) + 1;

        if(write(fd, buf, strsize) != strsize)
        {
                printf("Parent write to FIFO failed \n");
                exit(1);
        }


mac.tieu 11-22-2010 02:43 AM

Quote:

Originally Posted by mashhype (Post 4166811)
I think the O_NONBLOCK was screwing things up...
I still dont understand what that does...but when I took it out, it did what it was supposed to do...

Because 'read' funtion is blocked until there are something ready to read. You could try out O_NONBLOCK mode as well but you have to check return value of 'read' function in child process. If it return EAGAIN, you should read fd again.
Quote:

Originally Posted by mashhype (Post 4166811)
I took out the wait(&status) function as well...why did that fix my problem..anyone know?

wait(2) - Linux man page
Quote:

All of these system calls are used to wait for state changes in a child of the calling process, and obtain information about the child whose state has changed. A state change is considered to be: the child terminated; the child was stopped by a signal; or the child was resumed by a signal. In the case of a terminated child, performing a wait allows the system to release the resources associated with the child; if a wait is not performed, then terminated the child remains in a "zombie" state


All times are GMT -5. The time now is 04:36 PM.