From 53bfab080c124181e555f1c8b1f150d673847738 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 4 Aug 2022 17:18:54 +0200 Subject: [PATCH] BUG/MINOR: sink: fix a race condition between the writer and the reader This is the same issue as just fixed in b8e0fb97f ("BUG/MINOR: ring/cli: fix a race condition between the writer and the reader") but this time for sinks. They're also sucking the ring and present the same race at high write loads. This must be backported to 2.2 as well. See comments in the aforementioned commit for backport hints if needed. --- src/sink.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sink.c b/src/sink.c index 38a082ed43..889acd2f46 100644 --- a/src/sink.c +++ b/src/sink.c @@ -306,7 +306,7 @@ static void sink_forward_io_handler(struct appctx *appctx) struct ring *ring = sink->ctx.ring; struct buffer *buf = &ring->buf; uint64_t msg_len; - size_t len, cnt, ofs; + size_t len, cnt, ofs, last_ofs; int ret = 0; /* if stopping was requested, close immediately */ @@ -409,6 +409,7 @@ static void sink_forward_io_handler(struct appctx *appctx) HA_ATOMIC_INC(b_peek(buf, ofs)); ofs += ring->ofs; sft->ofs = ofs; + last_ofs = ring->ofs; } HA_RWLOCK_RDUNLOCK(LOGSRV_LOCK, &ring->lock); @@ -416,8 +417,16 @@ static void sink_forward_io_handler(struct appctx *appctx) /* let's be woken up once new data arrive */ HA_RWLOCK_WRLOCK(LOGSRV_LOCK, &ring->lock); LIST_APPEND(&ring->waiters, &appctx->wait_entry); + ofs = ring->ofs; HA_RWLOCK_WRUNLOCK(LOGSRV_LOCK, &ring->lock); - applet_have_no_more_data(appctx); + if (ofs != last_ofs) { + /* more data was added into the ring between the + * unlock and the lock, and the writer might not + * have seen us. We need to reschedule a read. + */ + applet_have_more_data(appctx); + } else + applet_have_no_more_data(appctx); } HA_SPIN_UNLOCK(SFT_LOCK, &sft->lock); -- 2.39.5