Set errno on EOF in syncRead and propagate it in logs (#3580)

When read() returns 0 (EOF/connection closed) in syncRead(), errno is
not set by POSIX, so it retains a stale value (typically 0). This causes
callers using connGetLastError() to log strerror(0) which is the
misleading string "Success".

Set errno = ECONNRESET on EOF in syncRead(), matching the existing
pattern used for the timeout case (errno = ETIMEDOUT).

Also set conn->last_errno = errno in connSocketSyncWrite,
connSocketSyncRead, and connSocketSyncReadLine wrappers, matching the
pattern used by their async counterparts connSocketWrite and
connSocketRead.

After this fix, replica logs will show:
  "I/O error reading bulk count from PRIMARY: Connection reset by peer"
instead of the misleading:
  "I/O error reading bulk count from PRIMARY: Success"

---------

Signed-off-by: Abhishek Mathur <matshek@amazon.com>
Signed-off-by: djk1027 <djk9510271@gmail.com>
Co-authored-by: Abhishek Mathur <matshek@amazon.com>
Co-authored-by: Daejun Kim <djk9510271@gmail.com>
Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
This commit is contained in:
abmathur-ie
2026-04-29 14:13:40 -07:00
committed by GitHub
parent 7817ca8a73
commit 678a06d216
3 changed files with 28 additions and 4 deletions
+15 -3
View File
@@ -391,15 +391,27 @@ static int connSocketBlockingConnect(connection *conn, const char *addr, int por
*/
static ssize_t connSocketSyncWrite(connection *conn, char *ptr, ssize_t size, long long timeout) {
return syncWrite(conn->fd, ptr, size, timeout);
ssize_t ret = syncWrite(conn->fd, ptr, size, timeout);
if (ret == -1) {
conn->last_errno = errno;
}
return ret;
}
static ssize_t connSocketSyncRead(connection *conn, char *ptr, ssize_t size, long long timeout) {
return syncRead(conn->fd, ptr, size, timeout);
ssize_t ret = syncRead(conn->fd, ptr, size, timeout);
if (ret == -1) {
conn->last_errno = errno;
}
return ret;
}
static ssize_t connSocketSyncReadLine(connection *conn, char *ptr, ssize_t size, long long timeout) {
return syncReadLine(conn->fd, ptr, size, timeout);
ssize_t ret = syncReadLine(conn->fd, ptr, size, timeout);
if (ret == -1) {
conn->last_errno = errno;
}
return ret;
}
static int connSocketGetType(void) {
+4 -1
View File
@@ -94,7 +94,10 @@ ssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout) {
/* Optimistically try to read before checking if the file descriptor
* is actually readable. At worst we get EAGAIN. */
nread = read(fd, ptr, size);
if (nread == 0) return -1; /* short read. */
if (nread == 0) {
errno = ECONNRESET;
return -1;
}
if (nread == -1) {
if (errno != EAGAIN) return -1;
} else {
+9
View File
@@ -1775,6 +1775,9 @@ static ssize_t connTLSSyncWrite(connection *conn_, char *ptr, ssize_t size, long
unsetBlockingTimeout(conn);
}
if (ret < 0) {
conn->c.last_errno = errno;
}
return ret;
}
@@ -1790,6 +1793,9 @@ static ssize_t connTLSSyncRead(connection *conn_, char *ptr, ssize_t size, long
unsetBlockingTimeout(conn);
}
if (ret < 0) {
conn->c.last_errno = errno;
}
return ret;
}
@@ -1827,6 +1833,9 @@ exit:
if (!blocking) {
unsetBlockingTimeout(conn);
}
if (nread < 0) {
conn->c.last_errno = errno;
}
return nread;
}