Version Information
ev-node: main branch
Execution Implementation: N/A
System Information
OS Type & Version: N/A (unit-level concurrency issue)
Architecture: N/A
Network Configuration
No response
Development Environment
Development Environment
Go Version: 1.25.8
Configuration Details
No response
Steps to Reproduce
- Create a
heightSub whose current height is below the requested height.
- Call
Wait with a context that is canceled shortly after registration.
- Repeat this operation for a height that is not reached.
- Inspect
heightSub.heightChs.
Example:
ctx, cancel := context.WithCancel(context.Background())
go hs.Wait(ctx, 10_000_000)
cancel()
Expected Result
Canceled waiters should be removed from heightSub.heightChs immediately.
Waiters registered for the same height should remain independent from each other.
Actual Result
Canceled waiters remain registered in heightSub.heightChs until notifyUpTo reaches the requested height. If that height is never reached, stale channels accumulate.
This can occur during normal P2P header/data sync cancellation and timeout lifecycles.
Relevant Logs
Additional Information
The proposed fix removes the specific canceled channel while holding heightMu. It also handles races between context cancellation and SetHeight without closing a channel twice.
Regression coverage should include:
- canceled waiters are removed;
- canceling one waiter does not remove other waiters at the same height;
- cancellation racing with
SetHeight does not cause a data race or panic.
Version Information
ev-node: main branch
Execution Implementation: N/A
System Information
OS Type & Version: N/A (unit-level concurrency issue)
Architecture: N/A
Network Configuration
No response
Development Environment
Development Environment
Go Version: 1.25.8
Configuration Details
No response
Steps to Reproduce
heightSubwhose current height is below the requested height.Waitwith a context that is canceled shortly after registration.heightSub.heightChs.Example:
Expected Result
Canceled waiters should be removed from
heightSub.heightChsimmediately.Waiters registered for the same height should remain independent from each other.
Actual Result
Canceled waiters remain registered in
heightSub.heightChsuntilnotifyUpToreaches the requested height. If that height is never reached, stale channels accumulate.This can occur during normal P2P header/data sync cancellation and timeout lifecycles.
Relevant Logs
Additional Information
The proposed fix removes the specific canceled channel while holding
heightMu. It also handles races between context cancellation andSetHeightwithout closing a channel twice.Regression coverage should include:
SetHeightdoes not cause a data race or panic.