fclose(3S) fclose(3S)
fclose, fflush - close or flush a stream
#include <stdio.h>
int fclose (FILE *stream<b>);
int fflush (FILE *stream<b>);
fclose causes any buffered data waiting to be written for the named
stream [see intro(3)] to be written out, and the stream to be closed. If
the underlying file pointer is not already at end of file, and the file
is one capable of seeking, the file pointer is adjusted so that the next
operation on the open file pointer deals with the byte after the last one
read from or written to the file being closed.
If stream points to an output stream or an update stream on which the
most recent operation was not input, fflush causes any buffered data
waiting to be written for the named stream to be written to that file.
Any unread data buffered in stream is discarded. The stream remains
open.
When calling fflush, if stream is a null pointer, all files open for
writing only and all files open for update whose last operation was a
write are flushed.
fflush(NULL) is performed automatically on calling exit.
If two streams point to the same underlying file descriptor, the
semantics associated with their use is complex. They are described in
detail in the POSIX90 1003.1 section 8.2.3. The most common way for an
unsuspecting application writer to wander into this situation is via
fork(2). fork of course replicates the process, including any stdio
buffers, while both the parent's and child's underlying file descriptor
share a common file offset pointer. This means that actions performed in
one process may affect the other. Consider the following:
Parent:
fp = fopen("foo", "r");
fread(buf, 100, 1, fp);
fork();
wait(NULL);
fread(buf, BUFSIZ+1, 1, fp);
Child:
fclose(fp);
exit(0);
The parent reads the first 100 bytes which really reads BUFSIZ bytes into
an internal stream buffer. The underlying file descriptor has its file
Page 1
fclose(3S) fclose(3S)
offset set to BUFSIZ. After the fork, the parent waits for the child.
The child calls fclose which causes the underlying file descriptor to be
synchronized with stream. In this case that means that an lseek on the
underlying file descriptor will be performed to set the file offset back
to 100. Since the file descriptor offset pointer is shared between
parent and child, the parent's file descriptor now points at offset 100.
When the parent continues reading and finishes the first buffer, a second
buffer will be read. The parent is assuming that the file offset is
still at BUFSIZ but the child's actions have changed it to 100. The
parent will get the incorrect data. The solution to this to either not
have the child call fclose or to synchronize the file descriptor with
stream before calling fork. Synchronization is done by calling
fflush(fp). Note that calling fflush(NULL) will not suffice since it
doesn't effect read only streams.
close(2), exit(2), intro(3), fopen(3S), setbuf(3S), stdio(3S)
On successful completion these functions return a value of zero.
Otherwise EOF is returned. For fflush(NULL), an error is returned if any
files encounter an error. For fclose, EOF is returned if stream is NULL,
or stream is not active, or there was an error when flushing buffered
writes, or there was an error closing the underlying file descriptor.
PPPPaaaaggggeeee 2222 [ Back ]
|