Fix possible hang after partial socket reads.

This commit is contained in:
Sönke Ludwig 2020-03-17 15:15:19 +01:00
parent 5c4e8be20a
commit 7c3fdc5ddf

View file

@ -455,31 +455,37 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets
assert(m_loop.m_fds[socket].common.refCount > 0); assert(m_loop.m_fds[socket].common.refCount > 0);
} }
sizediff_t ret = 0; while (true) {
() @trusted { ret = .recv(cast(sock_t)socket, slot.readBuffer.ptr, min(slot.readBuffer.length, int.max), 0); } (); sizediff_t ret = 0;
if (ret < 0) { () @trusted { ret = .recv(cast(sock_t)socket, slot.readBuffer.ptr, min(slot.readBuffer.length, int.max), 0); } ();
auto err = getSocketError(); if (ret < 0) {
if (!err.among!(EAGAIN, EINPROGRESS)) { auto err = getSocketError();
auto st = handleReadError(err, *slot); if (!err.among!(EAGAIN, EINPROGRESS)) {
finalize(st); auto st = handleReadError(err, *slot);
finalize(st);
return;
}
}
if (ret == 0 && slot.readBuffer.length) {
// treat as if the connection read end was shut down
handleReadError(ESHUTDOWN, m_loop.m_fds[socket].streamSocket);
finalize(IOStatus.disconnected);
return; return;
} }
}
if (ret == 0 && slot.readBuffer.length) { if (ret > 0 || !slot.readBuffer.length) {
// treat as if the connection read end was shut down slot.bytesRead += ret;
handleReadError(ESHUTDOWN, m_loop.m_fds[socket].streamSocket); slot.readBuffer = slot.readBuffer[ret .. $];
finalize(IOStatus.disconnected); if (slot.readMode != IOMode.all || slot.readBuffer.length == 0) {
return; finalize(IOStatus.ok);
} return;
}
if (ret > 0 || !slot.readBuffer.length) {
slot.bytesRead += ret;
slot.readBuffer = slot.readBuffer[ret .. $];
if (slot.readMode != IOMode.all || slot.readBuffer.length == 0) {
finalize(IOStatus.ok);
return;
} }
// retry if this was just a partial read, as it could mean that
// the connection was closed by the remove peer
if (ret <= 0 || !slot.readBuffer.length) break;
} }
} }