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.
Fix frame double-release for RequestResponse frame type.
Motivation:
One of our production services occasionally experiences the following panic:
After a brief investigation - I discovered that a RequestResponse frame gets double-released occasionally (dependent on a race condition):
onFinally
method here:rsocket-go/internal/socket/duplex.go
Line 258 in 099cb5b
onFinally
->unregister
->deleteFragment
call chain - here:rsocket-go/internal/socket/duplex.go
Line 799 in 099cb5b
Due to this double-release - it is possible for an
IncRef()
call on a frame to have no effect, the frame getting released pre-maturely and the above panic to be observed.For the particular panic observed - the following
IncRef()
may lose its effect (in certain race-scenarios) due to the erroneous double-release:rsocket-go/rx/mono/block_subscriber.go
Line 52 in 099cb5b
When the above
IncRef()
condition occurs - the followingpayload.Clone()
invocation will panic (as the frame would have already been released pre-maturely):rsocket-go/rx/mono/proxy_oneshot.go
Line 134 in 099cb5b
Modifications:
destroyFragment()
->destroyAllFragments()
for clarity and to avoid ambiguity withdestroyFragment(sid)
.common.TryRelease(handler.cache)
from theonFinally
method..cache
field from therequestResponseCallback
- as it seems that there is no need to cache the frame in the callback itself.Result:
The panic should go away after this change.