Reputation: 6901
So, this is a weird case that I am seeing sometimes and not able to figure out a reason.
We have a C program that reads from a regular file. And there are other processes which write into the same file. The application is based on the fact that the writes are atomic in Linux for write size up to 4096 bytes.
The file is NOT opened with non blocking flag, so my assumption is that reads would be blocking.
But sometimes during the startup, we see "Resource temporarily unavailable" error set in errno
. And the size returned by read != -1 but some partially read size.
An error message would look something like:
2018-08-07T06:40:52.991141Z, Invalid message size, log_s.bin, fd 670, Resource temporarily unavailable, read size 285, expected size 525
My questions are:
Why are we getting EAGAIN
on blocking file read?
Why is the return value not -1?
This happens only during the initial time when it is started. It works fine thereafter. What are some edge cases that can get us in such situation?
Upvotes: 1
Views: 2784
Reputation: 70883
Why are we getting EAGAIN on blocking file read ?
You aren't (see below).
Why is the return value not -1 ?
Because the operation did not fail.
The value of errno
only carries a sane value if the call to read()
failed. A call to read()
failed if and only if -1
is returned.
From the Linux man-page for read()
:
RETURN VALUE
On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested;
[...]
On error, -1 is returned, and
errno
is set appropriately.
A common pattern to read()
would be
char buffer[BUFFER_MAX];
char * p = buffer;
size_t to_read = ... /* not larger then BUFFER_MAX! */
while (to_read > 0)
{
ssize_t result = read(..., p, to_read);
if (-1 == result)
{
if (EAGAIN == errno || EWOULDBLOCK == errno)
{
continue;
}
if (EINTR == errno)
{
continue; /* or break depending on application design. */
}
perror("read() failed");
exit(EXIT_FAILURE);
}
else if (0 < result)
{
to_read -= (size_t) result;
p += (size_t) result;
}
else if (0 == result) /* end of file / connection shut down for reading */
{
break;
}
else
{
fprintf(stderr, "read() returned the unexpected value of %zd. You probably hit a (kernel) bug ... :-/\n", result);
exit(EXIT_FAILURE);
}
}
If (0 < to_read)
{
fprintf(stderr, "Encountered early end of stream. %zu bytes not read.\n", to_read);
}
Upvotes: 6