Re: fork() memory corruption... is this glibc2 or kernel?

Roderich Schupp (rsch@ExperTeam.de)
Sun, 21 Jun 1998 15:49:50 +0200


Just a follow up to my previous posting, but apparently my glance over
the Single Unix Spec v2 was just to quick :( Here's what is has to say,
in chapter `Standard I/O Streams'.

Note: a `handle' in their lingo is either a file descriptor e.g. as
returned from open() or a FILE pointer e.g. as returned from fopen().
The latter case is referred to as a `stream handle'.

The result of function calls involving any one handle (the active
handle) are defined elsewhere in this specification, but if two or
more handles are used, and any one of them is a stream, their actions
must be coordinated as described below. If this is not done, the
result is undefined. ...

For a handle to become the active handle, the actions below must be
performed between the last use of the handle (the current active
handle) and the first use of the second handle (the future active
handle). The second handle then becomes the active handle. All
activity by the application affecting the file offset on the first
handle must be suspended until it again becomes the active file
handle. (If a stream function has as an underlying function one that
affects the file offset, the stream function will be considered to
affect the file offset.)

The handles need not be in the same process for these rules to apply.

Note that after a fork(), two handles exist where one existed
before. The application must assure that, if both handles will ever be
accessed, that they will both be in a state where the other could
become the active handle first. The application must prepare for a
fork() exactly as if it were a change of active handle. (If the only
action performed by one of the processes is one of the exec functions
or _exit() (not exit()), the handle is never accessed in that
process.)

For the first handle, the first applicable condition below applies.
After the actions required below are taken, if the handle is still
open, the application can close it.

If it is a file descriptor, no action is required.
- If the only further action to be performed on any handle to this
open file descriptor is to close it, no
action need be taken.
- If it is a stream which is unbuffered, no action need be taken.
- If it is a stream which is line buffered, and the last byte
written to the stream was a newline (that is, as if a:
putc('\n')
was the most recent operation on that stream), no action need be
taken.
- If it is a stream which is open for writing or appending (but
not also open for reading), either an fflush() must be done, or the
stream must be closed.
- If the stream is open for reading and it is at the end of the
file (feof is true), no action need be taken.
- If the stream is open with a mode that allows reading and the
underlying open file description refers to a device
that is capable of seeking, either an fflush() must occur
or the stream must be closed.

Otherwise, the result is undefined.

That is, glibc is correct and the bug is in your program. And
issuing a fflush() before the fork() is the correct fix.

Cheers, Roderich

--
Neben Eden eben
Neben Amor
nie adretter
die Liebe grte!
Bier! Feten!
Gesegnete Freibetrge!
Bei Leid Retter da!
.. ein Roman eben.
Roderich Schupp                 mailto:rsch@ExperTeam.de
ExperTeam GmbH                  http://www.experteam.de/
Munich, Germany                 linux:2.1.106

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu