From b2e4aad9e2ad5d2971831d5e5a41e8916363e6c9 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 27 Feb 2018 10:40:40 +0100 Subject: [PATCH] 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. --- src/networking.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/networking.c b/src/networking.c index 3ade8a4f2..35f1fa261 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1011,13 +1011,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; -- GitLab