Fix another ProxySession and NetVC shutdown race crash #4178
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Thought I fixed this with 507368d, but after wider deployment of that fix, we got another crash on a freed client_vc. Another look at the ProxyClientSession::handle_api_return, shows that I missed the very obvious call to vc->do_io_close() before ProxyClientSession::free() which will trigger the exactly same freed client vc with stale reference. So the original fix is good but not sufficient.
Here is our most recent stack trace
Looking at frame 1, client_vc is non-null, but it has been freed (its vtable pointer is bogus). Looking back at ProxyClientSession::handle_api_return, were we removed the call to net_vc, we see there is still a problem.
We free the vc the call to do_io_close because we came in on the other vc, so this vc does not have its recursion count bumped. The Http2ClientSession still has a stale reference to the vc via its client_vc member, so then bad things can happen if that vc has already been freed.
Http2CientSession and Http1ClientSession both call do_io_close and clear the client VC in their ::do_io_close methods. But for their ::free methods only Http2ClientSession calls do_io_close on the client vc. Http1ClientSession does not.
Either both should or neither should. We cannot safely do both in handle_api_return. After calling ::free the session is gone, so we cannot reach in and clean up the VC afterwards. If we continue with the early vc->do_io_close, we would have to make another call to set the VC to null before calling into ::free.
At this point, it would be cleanest just to defer the client vc clean up to the Http*ClientSession::free logic, which is what I propose in this PR.