From 1ca213ee7cb6504561a314220312d4f0c2abc446 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 20 Mar 2025 10:31:15 +0300 Subject: [PATCH] [#12] mclock: Fix deadlock caused by mclock.Close Deadlock scenario: - mclock closed by `Close` method, it locks mutex and calls `clock.close` - clock starts `scheduleRequest` goroutine, it tries to lock mutex - `clock.Close` waits for all goroutines Signed-off-by: Dmitrii Stepanov --- scheduling/mclock.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scheduling/mclock.go b/scheduling/mclock.go index 6d13d5d..63a969c 100644 --- a/scheduling/mclock.go +++ b/scheduling/mclock.go @@ -137,15 +137,15 @@ func (q *MClock) RequestArrival(ctx context.Context, tag string) (ReleaseFunc, e // No new requests for scheduling will be accepted after the closing. func (q *MClock) Close() { q.mtx.Lock() - defer q.mtx.Unlock() - q.closed = true - q.clock.close() for q.limitQueue.Len() > 0 { item := heap.Pop(q.limitQueue).(*limitMQueueItem) close(item.r.canceled) q.removeFromQueues(item.r) } + q.mtx.Unlock() + + q.clock.close() } func validateParams(runLimit uint64, tagInfo map[string]TagInfo) error { @@ -261,6 +261,10 @@ func (q *MClock) scheduleRequest() { q.mtx.Lock() defer q.mtx.Unlock() + if q.closed { + return + } + q.scheduleRequestUnsafe() }