bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fwrite error reporting


From: Petr Vandrovec
Subject: Re: fwrite error reporting
Date: Tue, 03 Apr 2001 22:20:10 -0700

Ulrich Drepper wrote:
> 
> Petr Vandrovec <address@hidden> writes:
> 
> > while (bytes_to_write > 0) {
> >   int tmp = bytes_to_write > 1048576 ? 1048576 : bytes_to_write;
> >   int count = fwrite(pointer, 1, tmp, outstream);
> >   if (count <= 0) {
> >     return FATAL_ERROR;
> >   }
> >   bytes_to_write -= count;
> >   pointer += count;
> > }
> 
> fwrite() returns 0 if nothing gets written.  I have no idea why you
> claim to see something different.  Provide a complete example.

As was shown in strace, it claims that 32KB of data was written!

If you do not believe me, this simple example maybe forces you to
believe.
Total sum of all return values is 32768 bytes larger than what was
really 
written. If you'll replace loop below with code above, you'll just
get 32KB missing in the output file because of we believe that if
fwrite()
returns 32768, it really wrote 32768 bytes, or at least stored them
somewhere in the buffer (and for this example I believe that it is bug
that library splits this large write into two pieces - 32KB + 1M-32KB
one...
It should make just one write if buffer is empty; but it is only
performance
problem, not correctness one).

#include <stdio.h>

static char zero[1048576];

void main(void) {
        int i;
        unsigned long pos;
        unsigned long sum = 0;

        for (i = 0; i < 16; i++) {
                int count = fwrite(zero, 1, 1048576, stdout);
                sum += count;
                fprintf(stderr, "Ret: %d, Err: %d\n", count, ferror(stdout));
        }
        pos = ftell(stdout);
        fprintf(stderr, "Total: %ld (%lX)\n", pos, pos);
        fprintf(stderr, "Expect: %ld (%lX)\n", sum, sum);
}


bash-2.04$ ./x > tmpf
Ret: 1048576, Err: 0
Ret: 1048576, Err: 0
Ret: 1048576, Err: 0
Ret: 1048576, Err: 0
Ret: 1048576, Err: 0
Ret: 32768, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Ret: 1048576, Err: 1
Total: 15728640 (F00000)
Expect: 15761408 (F08000)

and file of course contains 15728640 zeroes, not 15761408 as one
could expect...
 
> It's the user's responsibility to check for errors.  If a write is
> short something bad happens and another call must be made for the
> not-written data.

I apologize - it sets ferror() condition, but fwrite() itself does
not check for this. We can live with this, as info pages do not
document that all operations until clearerr/rewind should fail.

But in this case fwrite() wrote nothing, stream buffer is empty, but
return value is 32768 instead of 0 !

> In general, using fwrite() is bad since it has far too many issues
> like this.  It's a horribly designed interface.

Do you have some replacement, or should we just throw all stdio.h out
of the window and use unistd's open/write/close interface? As write()
fails really often in our environment (mandatory locking and so on), 
we need to recover from such errors without need to restart write
process again from scratch.
                                        Petr Vandrovec
                                        address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]