NativeMessageQueue: ensure nativeDestroy success

android_os_MessageQueue_nativeDestroy leaves a cyclic reference between its Looper instance and its NativeMessageQueue instance, resulting in a memory and fd leak.

Solution: break the cyclic reference with weak pointer wp<>.

Bug: 244478726

Signed-off-by: Jintao Zhu <zhu.jintao@gm.com>
Change-Id: Ic2a183b5cc7c05f9ade95a0602d425badd3d97b1
This commit is contained in:
Jintao Zhu
2022-09-09 00:00:29 +08:00
committed by Jintao Zhu
parent 7f5baabe2a
commit 1b9cf90478

View File

@@ -51,6 +51,21 @@ public:
virtual int handleEvent(int fd, int events, void* data);
/**
* A simple proxy that holds a weak reference to a looper callback.
*/
class WeakLooperCallback : public LooperCallback {
protected:
virtual ~WeakLooperCallback();
public:
WeakLooperCallback(const wp<LooperCallback>& callback);
virtual int handleEvent(int fd, int events, void* data);
private:
wp<LooperCallback> mCallback;
};
private:
JNIEnv* mPollEnv;
jobject mPollObj;
@@ -131,7 +146,8 @@ void NativeMessageQueue::setFileDescriptorEvents(int fd, int events) {
if (events & CALLBACK_EVENT_OUTPUT) {
looperEvents |= Looper::EVENT_OUTPUT;
}
mLooper->addFd(fd, Looper::POLL_CALLBACK, looperEvents, this,
mLooper->addFd(fd, Looper::POLL_CALLBACK, looperEvents,
sp<WeakLooperCallback>::make(this),
reinterpret_cast<void*>(events));
} else {
mLooper->removeFd(fd);
@@ -162,6 +178,24 @@ int NativeMessageQueue::handleEvent(int fd, int looperEvents, void* data) {
}
// --- NativeMessageQueue::WeakLooperCallback ---
NativeMessageQueue::WeakLooperCallback::WeakLooperCallback(const wp<LooperCallback>& callback) :
mCallback(callback) {
}
NativeMessageQueue::WeakLooperCallback::~WeakLooperCallback() {
}
int NativeMessageQueue::WeakLooperCallback::handleEvent(int fd, int events, void* data) {
sp<LooperCallback> callback = mCallback.promote();
if (callback != nullptr) {
return callback->handleEvent(fd, events, data);
}
return 0;
}
// ----------------------------------------------------------------------------
sp<MessageQueue> android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) {