By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,498 Members | 1,713 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,498 IT Pros & Developers. It's quick & easy.

fread() blocks when reading pipe with closed write end

P: n/a
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);
}
}
~

Nov 15 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
>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
Nov 15 '05 #2

P: n/a
No, and no. Thank you! That was quite frustrating.

Nov 15 '05 #3

P: n/a
bill wrote:
No, and no. Thank you! That was quite frustrating.


What and what? Thank who? What was?

Brian

--
Please quote enough of the previous message for context. To do so from
Google, click "show options" and use the Reply shown in the expanded
header.
Nov 15 '05 #4

P: n/a
On 27 Oct 2005 11:03:18 -0700, "bill" <bi**********@gmail.com> wrote:
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>>
Nov 15 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.