Handle partial writes on non-blocking sockets

Now that we're using krb5_net_write() with non-blocking sockets in
ipropd_master, we MUST correctly account for partial writes.

Therefore, roken net_write() called from krb5_net_write() now
returns the number of bytes written when the socket error was
EWOULDBLOCK (or EAGAIN).

Also, fix potential issue on Windows, where errno was used instead
of rk_SOCKET_ERRNO whether or not we used _write() or send().
This commit is contained in:
Viktor Dukhovni
2019-11-06 20:27:58 -05:00
parent 9ca5d710f9
commit 12826c9586

View File

@@ -36,7 +36,9 @@
#include "roken.h"
/*
* Like write but never return partial data.
* Like write but blocking sockets never return partial data, i.e. we retry on
* EINTR. With non-blocking sockets (EWOULDBLOCK or EAGAIN) we return the
* number of bytes written.
*/
#ifndef _WIN32
@@ -51,11 +53,18 @@ net_write (rk_socket_t fd, const void *buf, size_t nbytes)
while (rem > 0) {
count = write (fd, cbuf, rem);
if (count < 0) {
if (errno == EINTR)
switch (errno) {
case EINTR:
continue;
else
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
case EWOULDBLOCK:
return nbytes - rem;
default:
return count;
}
}
cbuf += count;
rem -= count;
}
@@ -93,11 +102,26 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes)
count = send (sock, cbuf, rem, 0);
#endif
if (count < 0) {
if (errno == EINTR)
if (!use_write) {
switch (rk_SOCK_ERRNO) {
case WSAEINTR:
continue;
else
case WSAEWOULDBLOCK:
return nbytes - rem;
default:
return count;
}
} else {
switch (errno) {
case EINTR:
continue;
case EWOULDBLOCK:
return nbytes - rem;
default:
return count;
}
}
}
cbuf += count;
rem -= count;
}