diff options
author | antirez <antirez@gmail.com> | 2018-02-27 10:40:40 +0100 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2018-02-27 13:06:42 +0100 |
commit | 75987431f008e0072a70e7d5c001c1724a7fb421 (patch) | |
tree | 75c7e260176a5f5245d278c6924389c0ecc4e063 | |
parent | 533d0e0375d3999e7bdb7880d8d77e910284151a (diff) | |
download | redis-75987431f008e0072a70e7d5c001c1724a7fb421.tar.gz |
AOF: fix a bug that may prevent proper fsyncing when fsync=always.
In case the write handler is already installed, it could happen that we
serve the reply of a query in the same event loop cycle we received it,
preventing beforeSleep() from guaranteeing that we do the AOF fsync
before sending the reply to the client.
The AE_BARRIER mechanism, introduced in a previous commit, prevents this
problem. This commit makes actual use of this new feature to fix the
bug.
-rw-r--r-- | src/networking.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/src/networking.c b/src/networking.c index 35f50dcec..1c0ac7ff5 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1044,13 +1044,25 @@ int handleClientsWithPendingWrites(void) { /* Try to write buffers to the client socket. */ if (writeToClient(c->fd,c,0) == C_ERR) continue; - /* If there is nothing left, do nothing. Otherwise install - * the write handler. */ - if (clientHasPendingReplies(c) && - aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, + /* If after the synchronous writes above we still have data to + * output to the client, we need to install the writable handler. */ + if (clientHasPendingReplies(c)) { + int ae_flags = AE_WRITABLE; + /* For the fsync=always policy, we want that a given FD is never + * served for reading and writing in the same event loop iteration, + * so that in the middle of receiving the query, and serving it + * to the client, we'll call beforeSleep() that will do the + * actual fsync of AOF to disk. AE_BARRIER ensures that. */ + if (server.aof_state == AOF_ON && + server.aof_fsync == AOF_FSYNC_ALWAYS) + { + ae_flags |= AE_BARRIER; + } + if (aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, sendReplyToClient, c) == AE_ERR) - { - freeClientAsync(c); + { + freeClientAsync(c); + } } } return processed; |