clockwork icon indicating copy to clipboard operation
clockwork copied to clipboard

WithTimeout's cancel func returns before c.err is written

Open curt-hash opened this issue 8 months ago • 0 comments

ctx, cancel := clockwork.WithTimeout(...)

cancel() closes cancelCalled and returns immediately without waiting for c.err to be written.

In my use case, this creates a data race with mock.AssertExpectations, which runs at the end of a test and reflects arguments to mocked methods (including this ctx).

I can work around the issue by doing something like:

defer func() {
  cancel()
  <-ctx.Done()
}()

But this is awkward. I do not expect a goroutine to mutate the context after cancel returns.

I think adding <-ctx.Done() after close(cancelCalled) would eliminate the race.

I also noticed that ctx.Err() blocks until Done is closed. This seems inconsistent with a normal context: // If Done is not yet closed, Err returns nil.

curt-hash avatar May 13 '25 20:05 curt-hash