Drain()
causes an infinite loop in Next()
if it's waiting for messages
#1524
Labels
defect
Suspected defect such as a bug or regression
Observed behavior
Calling
Drain()
will cause an infinite loop inpullSubscription.Next()
if it's already blocking and waiting for messages.The code causing the issue:
The issue here is that when
Drain()
is called it closes thes.done
channel, so this code will cause an infinite loop.This issue is somehow related to #1343.
The check for the
s.done
channel was added in #1344.Possible solution
Closing the
s.done
channel is needed to exit frompullMessages()
and callcleanup()
to unsubscribe.Changing the way we exit in
Next()
might be a good solution, we can remove the check fors.done
being closed and rely ons.msgs
being closed to exit the loop (Closed in the subscription's close handler).But this might cause a deadlock with the current code.
Next()
holds the lock and whenDrain()
orStop()
are called, they close thes.done
channel which is used to stop pulling messages and callcleanup()
.The
cleanup()
function will block and wait for the lock so it won't be able to unsubscribe which is required to close thes.msgs
channel, so this leads to a deadlock.The current drain test does not have this issue because
Next()
does not block and wait for messages, it's called once for every published message (The lock is held and released multiple times so the cleanup method has a chance to run).Expected behavior
Calling
Drain()
should makeNext()
return with an errorErrMsgIteratorClosed
.Server and client version
nats-server:
v2.10.9
nats.go:
v1.32.0
Host environment
OS:
Linux
Arch:
amd64
Go:
v1.21.6
Steps to reproduce
Next()
in a goroutine so it blocks waiting for messages:Drain()
to unsubscribe:Minimal Reproducible Example
The text was updated successfully, but these errors were encountered: