fread() blocks when reading pipe with closed write end

B

bill

I am confused by the behavior of the following code. The function
copy() takes two FILE *'s and copies the data from one to the other.
In the main routine, I create a pipe and copy stdin to the write end
while copying the read end to stdout. If the child handles copying the
read end of the pipe to stdout, the main program returns. If the child
handles copying stdin to the write end of the pipe, the parent hangs in
copy(), blocking on fget() (or fread()). I've executed in gdb and
watched the child close the write end of the pipe before the parent
ever gets to the read, read the data off the pipe, and then block
indefinitely. The write end is closed, why doesn't fget() or fread()
return EOF? And why does the behavior change when the role of
parent/child is reversed? (replace "if(pid)" with "if(!pid)")

I've removed most of the error checking from this for clarity, but
point out that the fclose() succeeds. (I've tried replacing fclose
with close(filedes[1]), to no affect.)

#include<stdio.h>
#include<inttypes.h>

void
copy(FILE *in, FILE *out)
{
int x;
while( (x = fgetc(in)) != EOF)
if (fwrite( &x, sizeof(x),1,out) != 1)
break;
/*
while( fread(&x, sizeof(x),1,in) == 1)
if (fwrite( &x, sizeof(x),1,out) != 1)
break;
*/
return;
}

int
main()
{
int filedes[2];
FILE *a, *b;
int pid;

pipe(filedes);
a = fdopen(filedes[0],"r");
b = fdopen(filedes[1],"w");
pid = fork();
if (!pid) {
copy(a, stdout);
}
else {
int err;
copy (stdin, b);
err = fclose(b);
fprintf(stderr,"fclose returned: %d\n",err);
}
}
~
 
G

Gordon Burditt

I am confused by the behavior of the following code. The function
copy() takes two FILE *'s and copies the data from one to the other.
In the main routine, I create a pipe and copy stdin to the write end
while copying the read end to stdout. If the child handles copying the
read end of the pipe to stdout, the main program returns. If the child
handles copying stdin to the write end of the pipe, the parent hangs in
copy(), blocking on fget() (or fread()). I've executed in gdb and
watched the child close the write end of the pipe before the parent

Did the *parent* close the write end of the pipe?
ever gets to the read, read the data off the pipe, and then block
indefinitely. The write end is closed,

Are *ALL* of the write ends closed?
why doesn't fget() or fread()
return EOF? And why does the behavior change when the role of
parent/child is reversed? (replace "if(pid)" with "if(!pid)")

Gordon L. Burditt
 
B

Barry Schwarz

I am confused by the behavior of the following code. The function
copy() takes two FILE *'s and copies the data from one to the other.
In the main routine, I create a pipe and copy stdin to the write end
while copying the read end to stdout. If the child handles copying the
read end of the pipe to stdout, the main program returns. If the child
handles copying stdin to the write end of the pipe, the parent hangs in
copy(), blocking on fget() (or fread()). I've executed in gdb and
watched the child close the write end of the pipe before the parent
ever gets to the read, read the data off the pipe, and then block
indefinitely. The write end is closed, why doesn't fget() or fread()
return EOF? And why does the behavior change when the role of
parent/child is reversed? (replace "if(pid)" with "if(!pid)")

I've removed most of the error checking from this for clarity, but
point out that the fclose() succeeds. (I've tried replacing fclose
with close(filedes[1]), to no affect.)

#include<stdio.h>
#include<inttypes.h>

void
copy(FILE *in, FILE *out)
{
int x;
while( (x = fgetc(in)) != EOF)
if (fwrite( &x, sizeof(x),1,out) != 1)

In addition to any other problems, you read one byte but write more
than one (probably four).
break;
/*
while( fread(&x, sizeof(x),1,in) == 1)
if (fwrite( &x, sizeof(x),1,out) != 1)
break;
*/
return;
}

int
main()
{
int filedes[2];
FILE *a, *b;
int pid;

pipe(filedes);
a = fdopen(filedes[0],"r");
b = fdopen(filedes[1],"w");
pid = fork();
if (!pid) {
copy(a, stdout);
}
else {
int err;
copy (stdin, b);
err = fclose(b);
fprintf(stderr,"fclose returned: %d\n",err);
}
}
~


<<Remove the del for email>>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top