]> Cypherpunks repositories - gostls13.git/commit
runtime: prevent time.Timer.Reset(0) from deadlocking testing/synctest tests
authorNicholas S. Husin <nsh@golang.org>
Sat, 1 Nov 2025 15:15:58 +0000 (11:15 -0400)
committerGopher Robot <gobot@golang.org>
Sat, 1 Nov 2025 15:37:04 +0000 (08:37 -0700)
commit385dc33250336081c0c630938c3efede481eff76
tree4acee89caacfc3045bac4622c9cbf2fed7128730
parent99b724f4542f4d9fb4a2ceacbbd2a6d9367dc0f6
runtime: prevent time.Timer.Reset(0) from deadlocking testing/synctest tests

In Go 1.23+, timer channels behave synchronously. When we have a timer
channel (i.e. !async && t.isChan) we would lock the
runtime.timer.sendLock mutex at the beginning of
runtime.timer.modify()'s execution.

Calling time.Timer.Reset(0) within a testing/synctest test,
unfortunately, causes it to hang indefinitely. This is because the
runtime.timer.sendLock mutex ends up being locked twice before it could
be unlocked:

- When calling time.Timer.Reset(), runtime.timer.modify() would lock the
  mutex per usual.
- Due to the 0 argument, runtime.timer.modify() would also try to
  execute the bubbled timer immediately rather than adding them to a
  heap. However, in doing so, it uses runtime.timer.unlockAndRun(),
  which also locks the same mutex.

This CL solves this issue by making sure that a locked
runtime.timer.sendLock mutex is unlocked first, whenever we try to
execute bubbled timer immediately in the stack.

Fixes #76052

Change-Id: I66429b9bf6971400de95dcf2d5dc9670c3135492
Reviewed-on: https://go-review.googlesource.com/c/go/+/716883
Reviewed-by: Damien Neil <dneil@google.com>
Auto-Submit: Nicholas Husin <nsh@golang.org>
Reviewed-by: Nicholas Husin <husin@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
src/internal/synctest/synctest_test.go
src/runtime/time.go