From 1b9cf9047879ef8a98a3a6403fb15242acf71ade Mon Sep 17 00:00:00 2001 From: Jintao Zhu Date: Fri, 9 Sep 2022 00:00:29 +0800 Subject: [PATCH] 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 Change-Id: Ic2a183b5cc7c05f9ade95a0602d425badd3d97b1 --- core/jni/android_os_MessageQueue.cpp | 36 +++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp index f7a98d16f2e3d..30d9ea19be390 100644 --- a/core/jni/android_os_MessageQueue.cpp +++ b/core/jni/android_os_MessageQueue.cpp @@ -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& callback); + virtual int handleEvent(int fd, int events, void* data); + + private: + wp 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::make(this), reinterpret_cast(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& callback) : + mCallback(callback) { +} + +NativeMessageQueue::WeakLooperCallback::~WeakLooperCallback() { +} + +int NativeMessageQueue::WeakLooperCallback::handleEvent(int fd, int events, void* data) { + sp callback = mCallback.promote(); + if (callback != nullptr) { + return callback->handleEvent(fd, events, data); + } + return 0; +} + + // ---------------------------------------------------------------------------- sp android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) {