This is the mail archive of the cygwin mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: freopen/fread/popen bug

On Feb 27 07:40, Ken Brown wrote:
> On 2/27/2015 3:43 AM, Corinna Vinschen wrote:
> >On Feb 26 22:05, Ken Brown wrote:
> >>I'm not sure exactly where the bug is, but here's what happens (STC at the end):
> >>
> >>1. I use freopen to open a file "foo" and associate it with stdin.
> >>
> >>2. I use fread to read a byte from foo.
> >>
> >>3. I call popen, expecting the child process to have foo as its stdin, with
> >>the file-position indicator pointing to the second byte.  But instead the
> >>child sees an empty stdin.
> >>
> >>If I omit step 2, the child process does indeed have foo as its stdin.  Are
> >>my expectations wrong, or is this a bug?
> >
> >Wrong expectations.  Keep in mind that the default read mode using
> >stdio functions is buffered.  So your fread fills the buffer in f.
> >The buffer is typically something like 1K or 4K.  If the file is
> >shorter than that, the file pointer will be set to EOF when calling
> >popen.  Try this before calling fread:
> >
> >   setvbuf(f, NULL, _IONBF, 0);
> In the actual code that I'm debugging (part of texinfo), I think that would
> create an unacceptable performance penalty for the child process.
> What's really happening is that we need to peek at the first few bytes of f
> before deciding which program to call in popen.  After peeking, there's a
> call to fseek(f,0,0) before the popen, with the intention that the child
> receives a file pointer set to the beginning of the file.

This is non-portable.  If the seek operation can be performed within the
bytes already in the stream buffer, then fseek is not required to call

This is an old discussion in how far the state of streams has to be
adjusted when calling execve and what a child process may expect.  There
are two ways to handle it and two schools of thought, so there's no
right or wrong.

The only portable way to get what you want with fully buffered streams
is to call fflush() on the streams before calling fork/exec (which is
what popen is, basically).


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

Attachment: pgpN6YlB2j7wT.pgp
Description: PGP signature

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]