summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYossi Gottlieb <yossigo@gmail.com>2020-12-22 12:24:20 +0200
committerOran Agra <oran@redislabs.com>2021-01-12 16:25:37 +0200
commitf84c181eac4a1f53eb218588ff2051fc527daf7f (patch)
tree383f1dfe388d3bd2a8d158928ea5ea03a0b19c4c
parent8ff022636176e85e2ced75223fe64f95701772e8 (diff)
downloadredis-f84c181eac4a1f53eb218588ff2051fc527daf7f.tar.gz
Fix crashes with io-threads-do-reads enabled. (#8230)
Normally IO threads should simply read data from the socket into the buffer and attempt to parse it. If a protocol error is detected, a reply is generated which may result with installing a write handler which is not thread safe. This fix delays that until the client is processed back in the main thread. Fixes #8220 (cherry picked from commit e7047ec2fcc20e150c0c8cf29addf582638d7e80)
-rw-r--r--src/networking.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/networking.c b/src/networking.c
index 2c3a1d067..65a67021f 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -249,8 +249,14 @@ int prepareClientToWrite(client *c) {
if (!c->conn) return C_ERR; /* Fake client for AOF loading. */
/* Schedule the client to write the output buffers to the socket, unless
- * it should already be setup to do so (it has already pending data). */
- if (!clientHasPendingReplies(c)) clientInstallWriteHandler(c);
+ * it should already be setup to do so (it has already pending data).
+ *
+ * If CLIENT_PENDING_READ is set, we're in an IO thread and should
+ * not install a write handler. Instead, it will be done by
+ * handleClientsWithPendingReadsUsingThreads() upon return.
+ */
+ if (!clientHasPendingReplies(c) && !(c->flags & CLIENT_PENDING_READ))
+ clientInstallWriteHandler(c);
/* Authorize the caller to queue in the output buffer of this client. */
return C_OK;
@@ -3340,6 +3346,12 @@ int handleClientsWithPendingReadsUsingThreads(void) {
}
}
processInputBuffer(c);
+
+ /* We may have pending replies if a thread readQueryFromClient() produced
+ * replies and did not install a write handler (it can't).
+ */
+ if (!(c->flags & CLIENT_PENDING_WRITE) && clientHasPendingReplies(c))
+ clientInstallWriteHandler(c);
}
/* Update processed count on server */