Reputation: 2657
In the man
pages of Linux about write()
it's stated that in case of EINTR
or EAGAIN
write()
will return -1
. While performing a read()
one may retry if such errors are encountered. What should be done in such situations when performing a write()
?
Upvotes: 2
Views: 447
Reputation: 310840
You can retry in the case of EINTR.
You can only get EAGAIN/EWOULDBLOCK
if you're in non-blocking mode, and in those cases it isn't appropriate to just retry in a loop. You should select()
until the socket becomes writable, and then retry. That can only happen when the peer reads something, which is why it isn't appropriate to burn CPU cycles at the sending end.
Upvotes: 1
Reputation: 214
It is true that you may wrap calls to write()
by checking for EINTR
or EAGAIN
. A simple loop to try the write()
again in those cases is suggested in this question, and may work well:
Upvotes: -1
Reputation: 2826
As far as I know, a way to handle such cases involves wrapping the write()
call inside a function that checks the return value as well as the errno
variable.
Cases like EAGAIN
and EINTR
indicate situations where the write()
was unsuccessful because some signal interrupted it or O_NONBLOCK
was set but the write()
would block. This means you can retry the write()
by probing the errno
status.
I'm not sure, however, if it is guaranteed that write()
will eventually succeed if you insist (and, of course, if you don't get any different errno
status).
You could do something like
ssize_t insist_write(int fd, const void * buff, size_t cnt)
{
ssize_t ret;
size_t original_cnt = cnt;
while (cnt > 0)
{
ret = write(fd, buff, cnt);
if (ret < 0)
{
// EINTR for interrupted writes, EAGAIN - EWOULDBLOCK for file/socket
// blocking case (see man page)
if ((errno != EINTR) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
return ret;
else
ret = 0;
}
// update buff and remaining bytes to write
buff += ret;
cnt -= ret;
}
return original_cnt;
}
I have also seen code where the above case is handled by doing
if (ret < 0) { return ret; }
instead of what I wrote, implying that such cases would be handled on a per-application basis (one such example is specifying a maximum number of write()
attempts before returning -1
).
Upvotes: 1