From 3b823ed00a22e142e25137dccb5f1c4fbb318d3f Mon Sep 17 00:00:00 2001 From: Semyon Krestyaninov <krestyaninov@perx.ru> Date: Mon, 27 May 2024 11:32:09 +0000 Subject: [PATCH] =?UTF-8?q?fix(core):=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20deadlock=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BE=D0=B4=D0=BD=D0=BE=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D0=BE=D0=BC=20=D0=B2=D1=8B=D0=B7=D0=BE=D0=B2=D0=B5=20Buf?= =?UTF-8?q?feredWriteSyncer.Stop=20=D0=B8=20=D1=81=D0=B8=D0=BD=D1=85=D1=80?= =?UTF-8?q?=D0=BE=D0=BD=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BF=D0=BE?= =?UTF-8?q?=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D0=B2=D0=B0=D0=BB=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close #PRXS-2576 --- logs/zap/buffered_write_syncer.go | 36 ++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/logs/zap/buffered_write_syncer.go b/logs/zap/buffered_write_syncer.go index e862a79d..42fae2b1 100644 --- a/logs/zap/buffered_write_syncer.go +++ b/logs/zap/buffered_write_syncer.go @@ -71,28 +71,40 @@ func (ws *BufferedWriteSyncer) start() { ws.buffer = make([]*logs.Entry, 0, ws.MaxBufferSize) ws.syncQueue = make(chan []*logs.Entry, ws.MaxSyncQueueSize) ws.flushStop = make(chan struct{}) + ws.started = true ws.wg.Add(2) go ws.syncLoop() go ws.flushLoop() - - ws.started = true } +// Stop останавливает РІСЃРµ фоновые работы Рё синхронизирует оставшиеся записи func (ws *BufferedWriteSyncer) Stop() error { - ws.mu.Lock() - defer ws.mu.Unlock() + // Создаем РЅРѕРІСѓСЋ область видимости для блокировки мьютекса только РІ указанной секции + // Рто необходимо, чтобы предотвратить возможный deadlock, который может возникнуть + // если после блокировки мьютекса РїСЂРё остановке будет вызван Sync внутри flushLoop(), + // который будет ожидать освобождения мьютекса + stopped, err := func() (bool, error) { + ws.mu.Lock() + defer ws.mu.Unlock() + + if !ws.started || ws.stopped { + return false, nil + } + ws.stopped = true - if !ws.started || ws.stopped { - return nil - } - ws.stopped = true + close(ws.flushStop) // завершаем flushLoop + + err := ws.flush() // очищаем оставшиеся записи - close(ws.flushStop) // завершаем flushLoop + close(ws.syncQueue) // завершаем syncLoop - err := ws.flush() // очищаем оставшиеся записи + return true, err + }() - close(ws.syncQueue) // завершаем syncLoop + if !stopped { + return nil + } ws.wg.Wait() // дожидаемся завершения flushLoop Рё syncLoop @@ -127,7 +139,7 @@ func (ws *BufferedWriteSyncer) Sync() error { ws.mu.Lock() defer ws.mu.Unlock() - if ws.started { + if ws.started && !ws.stopped { return ws.flush() } -- GitLab