Handle response correctly when request already cancelled#110249
Conversation
|
Pinging @elastic/es-distributed (Team:Distributed) |
| if (localRefs.tryIncRef() == false) { | ||
| assert localRefs.hasReferences() == false : "tryIncRef failed but RefCounted not completed"; | ||
| return; | ||
| } |
There was a problem hiding this comment.
This feels like it could hide the test being broken (i.e. if we always cancel before the call to processResponse it'll happily pass without testing anything).
Another approach would be to put a synchronization point after the call to sendResponse, which we wait on before cancelling the request. That way we could be sure we'd begun sending the response before the cancellation? but perhaps handling cancellation prior to the response being sent is part of the test?
There was a problem hiding this comment.
I guess we could just call tryIncRef, and if it fails to increment the counter, it should also not decrement it later (by virtue of channel.sendResponse not sending the chunked response)?
There was a problem hiding this comment.
I think the current change is fine. We also do something similar at prepareRequest a few lines above.
perhaps handling cancellation prior to the response being sent is part of the test?
I think so. The random sleep in the test method is intended to have cancellation happen in different places, including in prepareRequest where no response is ever generated.
it should also not decrement it later (by virtue of channel.sendResponse not sending the chunked response)?
I think this might not be the case. It seems that response is released if channel.sendResponse fails to send.
With the changes in elastic#109519 we now do one more async step while serving the response, so we need to acquire another ref to track the new step. Relates elastic#109866 Relates elastic#110118 Relates elastic#110175 Relates elastic#110249
Related to #109866
Since #110118 the test fails under the same circumstances, but in a different way.
Now, when
processResponseexecutes after the cancellation has completed (localRefs.hasReferences() == false) - but before the channel is closed (RestActionListener.ensureOpen()passes), the call tomustIncRef()fails because the reference counts have already reached zero. This change usestryIncRef()instead, double-checking on a failure thathasReferences() == false(although I'm not sure whether that bit is necessary)