C Named pipe (fifo). Parent process gets stuck
Solution 1
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.
Solution 2
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.
AdrianS
Updated on June 26, 2022Comments
-
AdrianS almost 2 years
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); } }
-
AdrianS almost 14 yearsi 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
-
AdrianS almost 14 yearsnow i have: char c[2]; c[1] = 0; c[0]=0; c[0] = strlen(r); // c[0] is lets say 4 write(fp,c,1); //fp is the FIFO then in another process: //open pipe, i check for errors, but there are no errors, so it open fine char 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
-
jschmier almost 14 yearsIt 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 almost 14 yearsThere is also a good named pipe tutorial on the Sun Developer Network that you may find useful.