-
Notifications
You must be signed in to change notification settings - Fork 91
[fix][client] prevent garbage collection of token-supplier #412
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
Conversation
@RobertIndie @BewareMyPower Sorry I haven't used C++ much before, am I right to assume that's what I need to do? |
Yeah, compared to a successful workflow before (https://github.com/apache/pulsar-client-node/actions/runs/13716725396/job/38363013887):
It seems that there are two more open handles that keep Jest from exiting:
|
src/Client.cc
Outdated
@@ -138,7 +138,9 @@ Client::Client(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Client>(info) | |||
if (clientConfig.Has(CFG_AUTH) && clientConfig.Get(CFG_AUTH).IsObject()) { | |||
Napi::Object obj = clientConfig.Get(CFG_AUTH).ToObject(); | |||
if (obj.Has(CFG_AUTH_PROP) && obj.Get(CFG_AUTH_PROP).IsObject()) { | |||
Authentication *auth = Authentication::Unwrap(obj.Get(CFG_AUTH_PROP).ToObject()); | |||
this->authRef_ = Napi::Persistent(obj.Get(CFG_AUTH_PROP).As<Napi::Object>()); | |||
this->authRef_.SuppressDestruct(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SuppressDestruct()
suppresses the destruction of authRef_
, which is held by the Client
instance. Could you try removing this call?
This method is used here:
pulsar-client-node/src/Client.cc
Line 88 in b79ead0
constructor.SuppressDestruct(); |
However, constructor
is a static variable, whose lifetime is the same with the whole program. But here authRef_
's lifetime is the same with the Client
. Suppressing the destruction of authRef_
could cause memory leak.

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't have time looking deeper for now. But I assume that when the Client
destructs, the authRef_
will be destroyed as well unless you call SuppressDestruct()
.
The original issue happens just because auth
is a local variable that is referenced by the client config's authentication field. However, since it's now a field of Client
, whose lifetime should be longer than its config. We can now prevent the GC of auth
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/cc @RobertIndie Please help double confirm if there is anything wrong with my analysis above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's the case then perhaps removing that for the logger object will also stop that other open handle.
I am away this weekend, but will give this a go when I'm back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your analysis. I think it's better to add a test to verify it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I am on mobile just seen that you have done it and tests passed!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you help add a test to verify this change?
When using the new async token‐supplier API (
() => Promise<string>
) introduced in #395, the JSAuthentication
object and its backingThreadSafeFunction
can be garbage‐collected if no live JS references remain. After the initial token expires, Pulsar’s broker will send a new auth challenge and the native code crashes when it tries to invoke a finalized TSFN.By persisting a reference to the authentication object in the client it prevents the V8 garbage collector from dropping the token-supplier.