diff options
author | Yossi Gottlieb <yossigo@gmail.com> | 2020-12-22 12:24:20 +0200 |
---|---|---|
committer | Oran Agra <oran@redislabs.com> | 2021-01-12 16:25:37 +0200 |
commit | f84c181eac4a1f53eb218588ff2051fc527daf7f (patch) | |
tree | 383f1dfe388d3bd2a8d158928ea5ea03a0b19c4c | |
parent | 8ff022636176e85e2ced75223fe64f95701772e8 (diff) | |
download | redis-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.c | 16 |
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 */ |