[
https://issues.apache.org/jira/browse/FLINK-40667?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Rui Fan updated FLINK-40667:
----------------------------
Description:
`recover()` retains the source buffer via `retainBuffer()` at the call site,
before `segmentSerializerFor` (arg5) and
`ChannelStateFilteringHandler.filterAndRewrite`'s two early throws run — any of
which orphans the extra reference, so refCnt never reaches 0 and
`closeInternal()` later `free()`s a segment still held by a live
`NetworkBuffer`.
Fix: move the `retainBuffer()` down to the dispatcher's delegation into the
inner `GateFilterHandler` (whose `sourceBufferOwnershipTransferred` guard
already recycles on throw), so every earlier throw runs before ownership is
transferred.
was:
Ownership of the source buffer is transferred to the filtering handler too
early: `recover()` transfers it via `retainBuffer()` as an argument expression,
so the extra reference exists before `segmentSerializerFor` (arg5) evaluates
and before `ChannelStateFilteringHandler.filterAndRewrite`'s two early throws
run — any of which orphans it, so refCnt never reaches 0 and `closeInternal()`
later `free()`s a segment still held by a live `NetworkBuffer`. The inner
`GateFilterHandler` already owns the true transfer boundary
(`sourceBufferOwnershipTransferred`, flipped at `vc.setNextBuffer`), which is
where FLINK-40345 added the recycle-on-throw guard.
Fix: transfer ownership only at that boundary — pass the base buffer down and
`retainBuffer()` inside the inner handler right before `vc.setNextBuffer`, so
every pre-hand-off throw runs while the caller still owns the buffer and its
`finally` recycles it.
> Buffer ref-count leaks in CDR recovery filtering end in free() on a live
> segment
> --------------------------------------------------------------------------------
>
> Key: FLINK-40667
> URL: https://issues.apache.org/jira/browse/FLINK-40667
> Project: Flink
> Issue Type: Sub-task
> Components: Runtime / Checkpointing
> Reporter: Rui Fan
> Assignee: Rui Fan
> Priority: Major
>
> `recover()` retains the source buffer via `retainBuffer()` at the call site,
> before `segmentSerializerFor` (arg5) and
> `ChannelStateFilteringHandler.filterAndRewrite`'s two early throws run — any
> of which orphans the extra reference, so refCnt never reaches 0 and
> `closeInternal()` later `free()`s a segment still held by a live
> `NetworkBuffer`.
> Fix: move the `retainBuffer()` down to the dispatcher's delegation into the
> inner `GateFilterHandler` (whose `sourceBufferOwnershipTransferred` guard
> already recycles on throw), so every earlier throw runs before ownership is
> transferred.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)