summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2018-02-27 10:40:40 +0100
committerantirez <antirez@gmail.com>2018-02-27 13:06:42 +0100
commit75987431f008e0072a70e7d5c001c1724a7fb421 (patch)
tree75c7e260176a5f5245d278c6924389c0ecc4e063
parent533d0e0375d3999e7bdb7880d8d77e910284151a (diff)
downloadredis-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.c24
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;