Reputation: 2663
I'm writing to a file in chunks of about 10b to 16 000b, when suddenly every chunk gets cut off at around 4050 bytes (specifically, 4050, 4051 and 4074 bytes, in that order). This means subsequent writes will overwrite data that ought to have been written, messing up my data. Any chunk under 4050b is written out fine.
Unfortunately, I can't reproduce it. All I have is the messed up file, so I'm debugging looking for something that would cause this.
Debugging it, I realize c's write() function gets called under the hood (this is Java code, FileChannel.write(), but the standard library calls c's write and only checks that bytes written > 0), and that the docs for it do not guarantee that it will write out all data asked for, only that it will tell you how much was written.
I don't check bytes written back in Java land (but I do get it, the function signature is almost the exact same), so the fix is dead simple. However, since I can't reproduce this, I don't know that I've fixed the actual problem. So therefore I'm hoping some c guru can tell me either that I'm smoking crack, or that there are legitimate circumstances where write() will be unable to write more than about 4050 bytes at a time.
This is running on a 64-bit Linux Kernel, version 3.0.0-26.
Edit: To expand as per comments below:
I'm writing to a normal file system file. I'm not sure what non-blocking means in this context, I'm not using callbacks or anything, but explicitly telling the OS to flush to disk is not done for each chunk. The file is opened using Java's RandomAccessFile, 'rw' mode.
Upvotes: 1
Views: 1636
Reputation: 34294
From man 2 write
:
The number of bytes written may be less than count if, for example,
there is insufficient space on the underlying physical medium, or the
RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the
call was interrupted by a signal handler after having written less than
count bytes. (See also pipe(7).)
From man 2 setrlimit
:
RLIMIT_FSIZE
The maximum size of files that the process may create. Attempts
to extend a file beyond this limit result in delivery of a
SIGXFSZ signal. By default, this signal terminates a process,
but a process can catch this signal instead, in which case the
relevant system call (e.g., write(2), truncate(2)) fails with
the error EFBIG.
These limits can be seen using the following commands:
ulimit -Sf
ulimit -Hf
Or by using this C program:
#include <stdio.h>
#include <errno.h>
#include <sys/resource.h>
int main()
{
struct rlimit rl;
if (getrlimit(RLIMIT_FSIZE, &rl) == 0) {
printf("%d %d\n", rl.rlim_cur, rl.rlim_max);
} else {
fprintf(stderr, "error: %d\n", errno);
}
return 0;
}
Upvotes: 5
Reputation: 151
From the Linux Programmer's Manual, on write(1): "write() writes up to count bytes to the file..."
How much is written depends on what you are writing to and whether you are using synchronous writes or not.
E.g. if it's a pipe och a socket, you can't write more than a pipe/socket buffer full (in synchronous mode: More than what's available in the buffer).
Upvotes: 4
Reputation: 533870
The simplest way to reproduce the problem is to have a slow consumer. This will cause the send buffer to be almost full when you call write() meaning not all the data you give it can be written. You can reduce the send and receiver buffer sizes to make this problem more obvious.
Upvotes: 2