Skip to content

Commit a36f84d

Browse files
Alexey Sharpclaude
authored andcommitted
Fix mdbx async tx goroutine leak: buffer the result channel
When asyncTx.Apply/asyncRwTx.Apply/ApplyRw is called, it creates an unbuffered result channel (rc), sends a request to the mdbx thread, and waits in a select for either the result or ctx.Done(). If the context is cancelled while the mdbx thread is executing the function, the caller takes the ctx.Done() path and abandons rc. The mdbx thread then tries to send the result to the unbuffered rc, but nobody is reading — blocking the mdbx-locked goroutine forever. This manifests as exec3_parallel.go:180 stuck on "chan send" for the entire test timeout (56+ minutes), with the mdbx thread permanently locked. Fix: make rc buffered with capacity 1 so the mdbx thread can always complete its send even if the caller has abandoned the channel. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 058e084 commit a36f84d

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

db/kv/mdbx/kv_mdbx.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,7 @@ func NewAsyncTx(tx kv.Tx, queueSize int) *asyncTx {
819819
}
820820

821821
func (a *asyncTx) Apply(ctx context.Context, f func(kv.Tx) error) error {
822-
rc := make(chan error)
822+
rc := make(chan error, 1) // buffered: if caller abandons via ctx.Done(), the mdbx thread must not block
823823
a.requests <- &applyTx{rc, a.Tx, f}
824824
select {
825825
case err := <-rc:
@@ -843,7 +843,7 @@ func NewAsyncRwTx(tx kv.RwTx, queueSize int) *asyncRwTx {
843843
}
844844

845845
func (a *asyncRwTx) Apply(ctx context.Context, f func(kv.Tx) error) error {
846-
rc := make(chan error)
846+
rc := make(chan error, 1) // buffered: if caller abandons via ctx.Done(), the mdbx thread must not block
847847
a.requests <- &applyTx{rc, a.RwTx, f}
848848
select {
849849
case err := <-rc:
@@ -854,7 +854,7 @@ func (a *asyncRwTx) Apply(ctx context.Context, f func(kv.Tx) error) error {
854854
}
855855

856856
func (a *asyncRwTx) ApplyRw(ctx context.Context, f func(kv.RwTx) error) error {
857-
rc := make(chan error)
857+
rc := make(chan error, 1) // buffered: if caller abandons via ctx.Done(), the mdbx thread must not block
858858
a.requests <- &applyRwTx{rc, a.RwTx, f}
859859
select {
860860
case err := <-rc:

0 commit comments

Comments
 (0)