Closed etan-status closed 4 months ago
If stream is Finished
it should not change state to Error
, it should stay Finished
.
This is list of state machine transitions for AsyncStreams.
Running
-> Error
-> Closing
-> Closed
.Running
-> Stopped
-> Closing
-> Closed
.Running
-> Finished
-> Closing
-> Closed
.Running
-> Closing
-> Closed
.It still an issue but it should be done in different way, e.g. await noCancel rstream.buffer.transfer()
.
If you put a doAssert
in the CancelledError
handler of the final transfer
, that state == Finished
, you'll see that it gets hit when running Nimbus BN.
as in, it's case (3), but in-between Closing
-> Closed
, someone cancels, resulting in Closing
-> Error
-> Closing
-> Closed
-> Closed
. The Closed
state is hit twice, as both times Closing
is entered it enqueues the transition to Closed
.
OK, yeah, it could be that there is a better way to fix it. I'll close this one, as I don't know the intricacies there. But the state transition should be fixed, to disallow Closing --> Error
.
When a
BoundedStreamReader
finishes, it performs one finaltransfer
to signal EOF. If the other end subsequently closes the stream, state changes fromFinished
toClosing
and enqueues a callback that will finish the close operation. If thetransfer
is then cancelled, thestate
changes fromClosing
toError
. The stream will eventually be closed, so changes again fromError
toClosing
, and the cleanup callback is scheduled a second time. Each of the cleanup callbacks then proceeds toGC_unref
toudata
before changing the state toClosed
. The doubleGC_unref
only happens ifudata
is used.In practice, the buggy flow is triggered when
nimbus-eth2
interacts with Geth, and Geth provides a response withContent-Length
. This is the case for example when a block without transactions is fetched; otherwise, it usesTransfer-Encoding: chunked
. Luckily, that setup does not configureudata
, so there is no double free in practice. But, other applications that useudata
and use the cancellation flow that triggers the bug may be affected.