Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: reference counting (retain/release) in PerChannelBookieClient #4293

Conversation

lhotari
Copy link
Member

@lhotari lhotari commented Apr 16, 2024

Motivation

This addresses the remaining gaps of #4289 in handling ByteBuf retain/release.
This PR will also address the concern about NioBuffer lifecycle brought up in the review of the original PR review: #791 (comment) .

This PR fixes several problems:

  • ByteString buffer lifecycle in client, follows ByteBufList lifecycle
  • ByteBufList lifecycle, moved to write promise
  • Calling of write promises in AuthHandler which buffers messages while authentication is in progress. It was ignoring the promises.

Changes

  • add 2 callback parameters to writeAndFlush: cleanupActionFailedBeforeWrite and cleanupActionAfterWrite
    • use these callback actions for proper cleanup
  • extract a utility class ByteStringUtil for wrapping ByteBufList or ByteBuf as concatenated zero copy ByteString
  • properly handle releasing of ByteBufList in the write promise
  • properly handle calling promises that are buffered while authentication is in progress

@lhotari lhotari force-pushed the lh-fix-reference-counts-in-PerChannelBookieClient branch from 37fe66d to 98bc499 Compare April 16, 2024 10:55
@lhotari lhotari changed the title fix: reference counts in PerChannelBookieClient fix: reference counting (retain/release) in PerChannelBookieClient Apr 16, 2024
@lhotari lhotari force-pushed the lh-fix-reference-counts-in-PerChannelBookieClient branch 10 times, most recently from 1a7542d to 90f9325 Compare April 16, 2024 12:05
@lhotari lhotari force-pushed the lh-fix-reference-counts-in-PerChannelBookieClient branch from 90f9325 to 77b09c2 Compare April 22, 2024 14:41
@lhotari
Copy link
Member Author

lhotari commented Apr 22, 2024

@hangc0276 @poorbarcode Please review. This addresses the remaining gaps of #4289.

@lhotari
Copy link
Member Author

lhotari commented Apr 26, 2024

@hangc0276 @poorbarcode @codelipenghui @BewareMyPower @merlimat Please review. This addresses the remaining gaps of #4289.

Copy link
Contributor

@dlg99 dlg99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a small comment

@lhotari lhotari force-pushed the lh-fix-reference-counts-in-PerChannelBookieClient branch from 77b09c2 to 74f9782 Compare May 23, 2024 19:12
@lhotari
Copy link
Member Author

lhotari commented May 23, 2024

I finally found the root cause in Bookkeeper client. The client had several buffer leaks since the ByteBufList lifecycle was incorrectly handled and write promises were dropped and ignored when authentication was in progress.
@merlimat @hangc0276 @poorbarcode @eolivelli @nicoloboschi @dlg99 Please review!
I hope we could release 4.16.6 after this PR is processed, merged and cherry-picked to branch-4.16 .

@shoothzj
Copy link
Member

Can we close #3902 after this pr is merged?

ChannelPromise promise;
// check if the message has an associated promise as the next element in the queue
if (waitingForAuth.peek() instanceof ChannelPromise) {
promise = (ChannelPromise) waitingForAuth.poll();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If found this issue before https://github.com/apache/bookkeeper/pull/3902/files. Your solution is better.

body = UnsafeByteOperations.unsafeWrap(toSend.toArray());
}
ByteString body = ByteStringUtil.byteBufListToByteString(toSend);
toSend.retain();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toSend already convert to ByteString, why do we need to retain and release after flushed no matter the flush succeed or not?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ByteString doesn't handle the lifecycle of the buffers referenced by the ByteString.
It's the toSend.retain() which handles the lifecycle.
The cleanupActionFailedBeforeWrite and cleanupActionAfterWrite parameters (Runnables) are used to ensure that the reference count is properly decreased later.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already converted toSend to ByteString, the lifecycle of toSend can be tracked by the caller of the method.

}
}
ByteString body = ByteStringUtil.byteBufListToByteString(bufToSend);
bufToSend.retain();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not need retain the bufToSend?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same answer as #4293 (comment)

@hangc0276
Copy link
Contributor

Nice catch!

@shoothzj shoothzj merged commit 0ef2f99 into apache:master May 24, 2024
21 checks passed
shoothzj pushed a commit that referenced this pull request May 25, 2024
…4293)

### Motivation

This addresses the remaining gaps of #4289 in handling ByteBuf retain/release.
This PR will also address the concern about NioBuffer lifecycle brought up in the review of the original PR review: #791 (comment) .

This PR fixes several problems:
* ByteString buffer lifecycle in client, follows ByteBufList lifecycle
* ByteBufList lifecycle, moved to write promise
* Calling of write promises in AuthHandler which buffers messages while authentication is in progress. It was ignoring the promises.

### Changes

- add 2 callback parameters to writeAndFlush: cleanupActionFailedBeforeWrite and cleanupActionAfterWrite
  - use these callback actions for proper cleanup
- extract a utility class ByteStringUtil for wrapping ByteBufList or ByteBuf as concatenated zero copy ByteString
- properly handle releasing of ByteBufList in the write promise
- properly handle calling promises that are buffered while authentication is in progress

(cherry picked from commit 0ef2f99)
ChannelPromise compositePromise = ctx.newPromise();
compositePromise.addListener(future -> {
// release the ByteBufList after the write operation is completed
ReferenceCountUtil.safeRelease(b);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ReferenceCountUtil.relesse(b) to expose potential exceptions in release the ByteBufList?

zhiheng123 pushed a commit to zhiheng123/bookkeeper that referenced this pull request May 26, 2024
…pache#4293)

This addresses the remaining gaps of apache#4289 in handling ByteBuf retain/release.
This PR will also address the concern about NioBuffer lifecycle brought up in the review of the original PR review: apache#791 (comment) .

This PR fixes several problems:
* ByteString buffer lifecycle in client, follows ByteBufList lifecycle
* ByteBufList lifecycle, moved to write promise
* Calling of write promises in AuthHandler which buffers messages while authentication is in progress. It was ignoring the promises.

- add 2 callback parameters to writeAndFlush: cleanupActionFailedBeforeWrite and cleanupActionAfterWrite
  - use these callback actions for proper cleanup
- extract a utility class ByteStringUtil for wrapping ByteBufList or ByteBuf as concatenated zero copy ByteString
- properly handle releasing of ByteBufList in the write promise
- properly handle calling promises that are buffered while authentication is in progress
lhotari added a commit to lhotari/bookkeeper that referenced this pull request May 27, 2024
…pache#4293)

### Motivation

This addresses the remaining gaps of apache#4289 in handling ByteBuf retain/release.
This PR will also address the concern about NioBuffer lifecycle brought up in the review of the original PR review: apache#791 (comment) .

This PR fixes several problems:
* ByteString buffer lifecycle in client, follows ByteBufList lifecycle
* ByteBufList lifecycle, moved to write promise
* Calling of write promises in AuthHandler which buffers messages while authentication is in progress. It was ignoring the promises.

### Changes

- add 2 callback parameters to writeAndFlush: cleanupActionFailedBeforeWrite and cleanupActionAfterWrite
  - use these callback actions for proper cleanup
- extract a utility class ByteStringUtil for wrapping ByteBufList or ByteBuf as concatenated zero copy ByteString
- properly handle releasing of ByteBufList in the write promise
- properly handle calling promises that are buffered while authentication is in progress

(cherry picked from commit 0ef2f99)

# Conflicts:
#	bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
shoothzj pushed a commit that referenced this pull request May 27, 2024
…4293) (#4396)

### Motivation

This addresses the remaining gaps of #4289 in handling ByteBuf retain/release.
This PR will also address the concern about NioBuffer lifecycle brought up in the review of the original PR review: #791 (comment) .

This PR fixes several problems:
* ByteString buffer lifecycle in client, follows ByteBufList lifecycle
* ByteBufList lifecycle, moved to write promise
* Calling of write promises in AuthHandler which buffers messages while authentication is in progress. It was ignoring the promises.

### Changes

- add 2 callback parameters to writeAndFlush: cleanupActionFailedBeforeWrite and cleanupActionAfterWrite
  - use these callback actions for proper cleanup
- extract a utility class ByteStringUtil for wrapping ByteBufList or ByteBuf as concatenated zero copy ByteString
- properly handle releasing of ByteBufList in the write promise
- properly handle calling promises that are buffered while authentication is in progress

(cherry picked from commit 0ef2f99)

# Conflicts:
#	bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants