Apparent bug in fclose()-exec()-freopen() sequence

Maarten Litmaath maart at cs.vu.nl
Sat Jun 17 15:50:17 AEST 1989


keith at fstohp.crd.ge.com (Keith D Gregory) writes:
\...
\As a guess, the startup code in P2 is initalizing its _iob array,
\and the call to fclose() (as part of freopen()) is thinking that
\the structure refers to a valid stream.
\
\Is this what is happening?

Yes. See below.

\Is there any reason (documented) that
\we should not close a file before exec()ing a program?

Yes. See below.

\...
\# Program 1 Start, Cut here ###################################################
\#include <stdio.h>
\
\void main()
\{
\    fclose( stdin );
\    fclose( stdout );
\    fclose( stderr );
\
\    execl( "p2", "p2", NULL );
\}

Now file descriptors 0, 1 and 2 are all unused! Read on.

\# Program 2 Start, Cut here ###################################################
\#include <stdio.h>
\
\void main()
\{
\    if (freopen( "/dev/tty", "w", stderr) == NULL)

Which file descriptor will freopen() get for stderr?
Right: number 0 (== the first unused).

\        exit( -1 );
\    else
\        fprintf( stderr, "Reopened StdErr, Flags = %d, FileNo = %d\n",
\                         stderr->_flag, stderr->_file );
\
\    fflush( stderr );
\
\    if (freopen( "/etc/passwd", "r", stdin) == NULL)
\...

Guess what stdin->_file is initialized too?
Right! ZERO.
Guess what the freopen() does first?
Right: a close(stdin->_file).
Guess whose file descriptor we've just managed to destroy?
Right again! stderr->_file is now closed too... :-(
It will be opened again READONLY, due to the "r" argument of freopen().
Hence perror() etc. fail.

One might consider the static initialization of stdin/stdout/stderr a bad
feature in the stdio implementation.
On the other hand, you do some pretty strange things, so you could
expect strange results.
One should provide every program will valid file descriptors 0, 1 and 2.
If you don't want the program to do anything with them, just connect them
to /dev/null.
If the program isn't interested in the pre-connected files, it could close()
the descriptors itself, e.g. implicitly by freopen().



More information about the Comp.unix.wizards mailing list