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:
@@ -36,7 +36,9 @@
|
|||||||
#include "roken.h"
|
#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
|
#ifndef _WIN32
|
||||||
@@ -51,10 +53,17 @@ net_write (rk_socket_t fd, const void *buf, size_t nbytes)
|
|||||||
while (rem > 0) {
|
while (rem > 0) {
|
||||||
count = write (fd, cbuf, rem);
|
count = write (fd, cbuf, rem);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
if (errno == EINTR)
|
switch (errno) {
|
||||||
|
case EINTR:
|
||||||
continue;
|
continue;
|
||||||
else
|
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
|
||||||
|
case EAGAIN:
|
||||||
|
#endif
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
return nbytes - rem;
|
||||||
|
default:
|
||||||
return count;
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cbuf += count;
|
cbuf += count;
|
||||||
rem -= count;
|
rem -= count;
|
||||||
@@ -93,10 +102,25 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes)
|
|||||||
count = send (sock, cbuf, rem, 0);
|
count = send (sock, cbuf, rem, 0);
|
||||||
#endif
|
#endif
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
if (errno == EINTR)
|
if (!use_write) {
|
||||||
continue;
|
switch (rk_SOCK_ERRNO) {
|
||||||
else
|
case WSAEINTR:
|
||||||
return count;
|
continue;
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
return nbytes - rem;
|
||||||
|
default:
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (errno) {
|
||||||
|
case EINTR:
|
||||||
|
continue;
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
return nbytes - rem;
|
||||||
|
default:
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cbuf += count;
|
cbuf += count;
|
||||||
rem -= count;
|
rem -= count;
|
||||||
|
Reference in New Issue
Block a user