From e9461686b87496c5d60e7ce8899865f267c3abc1 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Thu, 20 Apr 2023 18:51:16 +0300 Subject: [PATCH] [#274] wc: Resolve possible deadlock If operation with WC are _fast enough_ (e.g. `Init` failed and `Close` is called immediately) there is a race and a deadlock that do not allow finish (and start, in fact) an initialization routine because of taken `modeMtx` and also do not allow finish `Close` call because of awaiting initialization finish. So do stop initialization _before_ any mutex is taken. Signed-off-by: Pavel Karpy --- pkg/local_object_storage/writecache/mode.go | 20 +++++++++---------- .../writecache/writecache.go | 3 --- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index 20b0cce2..14f8af49 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -29,9 +29,6 @@ func (c *cache) SetMode(m mode.Mode) error { )) defer span.End() - c.modeMtx.Lock() - defer c.modeMtx.Unlock() - return c.setMode(ctx, m) } @@ -40,13 +37,6 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode) error { var err error turnOffMeta := m.NoMetabase() - if turnOffMeta && !c.mode.NoMetabase() { - err = c.flush(ctx, true) - if err != nil { - return err - } - } - if !c.initialized.Load() { close(c.stopInitCh) @@ -60,6 +50,16 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode) error { }() } + c.modeMtx.Lock() + defer c.modeMtx.Unlock() + + if turnOffMeta && !c.mode.NoMetabase() { + err = c.flush(ctx, true) + if err != nil { + return err + } + } + if c.db != nil { if err = c.db.Close(); err != nil { return fmt.Errorf("can't close write-cache database: %w", err) diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 0fc2e601..bdcc9bbf 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -163,9 +163,6 @@ func (c *cache) Init() error { // Close closes db connection and stops services. Executes ObjectCounters.FlushAndClose op. func (c *cache) Close() error { - c.modeMtx.Lock() - defer c.modeMtx.Unlock() - // Finish all in-progress operations. if err := c.setMode(context.TODO(), mode.ReadOnly); err != nil { return err