summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcore_mac_objc.mm
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2019-02-12 13:02:48 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2019-02-13 12:37:00 +0000
commit6c18f86af7affc60a571c65f0b335d7ee8947100 (patch)
tree89e2765f85fd8ff153e91d2939f286e3b738b770 /src/corelib/kernel/qcore_mac_objc.mm
parentd6c474b49b349dc6c30ea059040285221e712217 (diff)
Track call sites of QMacAutoReleasePools for debugging pool usage
Printing pools by calling [NSAutoreleasePool showPools] will now give a more detailed view of where the various pools in the stack were created, eg: AUTORELEASE POOLS for thread 0x1000be5c0 17 releases pending. [0x107802000] ................ PAGE (hot) (cold) [0x107802038] ################ POOL 0x107802038 [0x107802040] 0x107791c70 ^-- allocated in function: main [0x107802048] ################ POOL 0x107802048 [0x107802050] 0x1073b2e80 ^-- allocated in function: QCocoaWindow::initialize() [0x107802058] 0x107111ed0 NSCompositeAppearance [0x107802060] 0x107111ed0 NSCompositeAppearance [0x107802068] 0x107111ed0 NSCompositeAppearance [0x107802070] 0x1073bbe10 __NSCFString [0x107802078] 0x1073bbde0 _NSViewBackingLayer [0x107802080] 0x1073bc100 NSWeakObjectValue [0x107802088] 0x1073bbe40 QNSView [0x107802090] 0x1073bbe40 QNSView [0x107802098] 0x107111ed0 NSCompositeAppearance [0x1078020a0] 0x107111ed0 NSCompositeAppearance [0x1078020a8] 0x1073bbe40 QNSView [0x1078020b0] ################ POOL 0x1078020b0 [0x1078020b8] 0x1073bbe30 ^-- allocated in function: QCocoaWindow::recreateWindowIfNeeded() Change-Id: I97faf30db5835fea2f05320435b1b8c334a478d1 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/corelib/kernel/qcore_mac_objc.mm')
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm59
1 files changed, 48 insertions, 11 deletions
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 140c60a080..4550891e2a 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -48,6 +48,11 @@
#include <UIKit/UIKit.h>
#endif
+#include <execinfo.h>
+#include <dlfcn.h>
+#include <cxxabi.h>
+#include <objc/runtime.h>
+
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@@ -127,22 +132,54 @@ QT_USE_NAMESPACE
}
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
-QT_BEGIN_NAMESPACE
-
-/*
- Manages a scoped auto-release pool.
-
- To track autoreleases without any pools in place, such as in main()
- before the runloop has started, export OBJC_DEBUG_MISSING_POOLS=YES
- and break in objc_autoreleaseNoPool, e.g.:
+QT_BEGIN_NAMESPACE
- br set -n objc_autoreleaseNoPool -c "[((NSObject*)$r14) class] == [QNSWindow class]"
-*/
QMacAutoReleasePool::QMacAutoReleasePool()
: pool([[NSAutoreleasePool alloc] init])
{
- [[[QMacAutoReleasePoolTracker alloc] initWithPool:
+ Class trackerClass = [QMacAutoReleasePoolTracker class];
+
+#ifdef QT_DEBUG
+ void *poolFrame = nullptr;
+ if (__builtin_available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 5.0, *)) {
+ void *frame;
+ if (backtrace_from_fp(__builtin_frame_address(0), &frame, 1))
+ poolFrame = frame;
+ } else {
+ static const int maxFrames = 3;
+ void *callstack[maxFrames];
+ if (backtrace(callstack, maxFrames) == maxFrames)
+ poolFrame = callstack[maxFrames - 1];
+ }
+
+ if (poolFrame) {
+ Dl_info info;
+ if (dladdr(poolFrame, &info) && info.dli_sname) {
+ const char *symbolName = info.dli_sname;
+ if (symbolName[0] == '_') {
+ int status;
+ if (char *demangled = abi::__cxa_demangle(info.dli_sname, nullptr, 0, &status))
+ symbolName = demangled;
+ }
+
+ char *className = nullptr;
+ asprintf(&className, " ^-- allocated in function: %s", symbolName);
+
+ if (Class existingClass = objc_getClass(className))
+ trackerClass = existingClass;
+ else
+ trackerClass = objc_duplicateClass(trackerClass, className, 0);
+
+ free(className);
+
+ if (symbolName != info.dli_sname)
+ free((char*)symbolName);
+ }
+ }
+#endif
+
+ [[[trackerClass alloc] initWithPool:
reinterpret_cast<NSAutoreleasePool **>(&pool)] autorelease];
}