summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcore_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qcore_mac.mm')
-rw-r--r--src/corelib/kernel/qcore_mac.mm124
1 files changed, 58 insertions, 66 deletions
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
index 989e7d03a6..54c4373aed 100644
--- a/src/corelib/kernel/qcore_mac.mm
+++ b/src/corelib/kernel/qcore_mac.mm
@@ -25,7 +25,6 @@
#include "qendian.h"
#include "qhash.h"
-#include "qpair.h"
#include "qmutex.h"
#include "qvarlengtharray.h"
#include "private/qlocking_p.h"
@@ -53,6 +52,7 @@ QT_BEGIN_NAMESPACE
// --------------------------------------------------------------------------
+#if defined(Q_OS_MACOS)
static void initializeStandardUserDefaults()
{
// The standard user defaults are initialized from an ordered list of domains,
@@ -65,6 +65,7 @@ static void initializeStandardUserDefaults()
Q_UNUSED(NSUserDefaults.standardUserDefaults);
}
Q_CONSTRUCTOR_FUNCTION(initializeStandardUserDefaults);
+#endif
// --------------------------------------------------------------------------
@@ -86,17 +87,35 @@ QCFString::operator CFStringRef() const
#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
-bool AppleUnifiedLogger::willMirrorToStderr()
+bool AppleUnifiedLogger::preventsStderrLogging()
{
- // When running under Xcode or LLDB, one or more of these variables will
- // be set, which triggers libsystem_trace.dyld to log messages to stderr
- // as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables
- // is not an option, as that would silence normal NSLog or os_log calls,
- // so instead we skip our own stderr output. See rdar://36919139.
+ // os_log will mirror to stderr if OS_ACTIVITY_DT_MODE is set,
+ // regardless of its value. OS_ACTIVITY_MODE then controls whether
+ // to include info and/or debug messages in this mirroring.
+ // For some reason, when launched under lldb (via Xcode or not),
+ // all levels are included.
+
+ // CFLog will normally log to both stderr, and via os_log.
+ // Setting CFLOG_FORCE_DISABLE_STDERR disables the stderr
+ // logging. Setting CFLOG_FORCE_STDERR will both duplicate
+ // CFLog's output to stderr, and trigger OS_ACTIVITY_DT_MODE,
+ // resulting in os_log calls also being mirrored to stderr.
+ // Setting ACTIVITY_LOG_STDERR has the same effect.
+
+ // NSLog is plumbed to CFLog, and will respond to the same
+ // environment variables as CFLog.
+
+ // We want to disable Qt's default stderr log handler when
+ // os_log has already mirrored to stderr.
static bool willMirror = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE")
- || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR")
- || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR");
- return willMirror;
+ || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR")
+ || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR");
+
+ // As well as when we suspect that Xcode is going to present os_log
+ // as structured log messages.
+ static bool disableStderr = qEnvironmentVariableIsSet("CFLOG_FORCE_DISABLE_STDERR");
+
+ return willMirror || disableStderr;
}
QT_MAC_WEAK_IMPORT(_os_log_default);
@@ -137,7 +156,7 @@ bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogCont
// system from redacting our log message.
os_log_with_type(log, logType, "%{public}s", qPrintable(message));
- return willMirrorToStderr();
+ return preventsStderrLogging();
}
os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType)
@@ -214,52 +233,38 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
QT_END_NAMESPACE
QT_USE_NAMESPACE
+
+#ifdef QT_DEBUG
@interface QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) : NSObject
@end
-@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) {
- NSAutoreleasePool **m_pool;
-}
-
-- (instancetype)initWithPool:(NSAutoreleasePool **)pool
-{
- if ((self = [self init]))
- m_pool = pool;
- return self;
-}
-
-- (void)dealloc
-{
- if (*m_pool) {
- // The pool is still valid, which means we're not being drained from
- // the corresponding QMacAutoReleasePool (see below).
-
- // QMacAutoReleasePool has only a single member, the NSAutoreleasePool*
- // so the address of that member is also the QMacAutoReleasePool itself.
- QMacAutoReleasePool *pool = reinterpret_cast<QMacAutoReleasePool *>(m_pool);
- qWarning() << "Premature drain of" << pool << "This can happen if you've allocated"
- << "the pool on the heap, or as a member of a heap-allocated object. This is not a"
- << "supported use of QMacAutoReleasePool, and might result in crashes when objects"
- << "in the pool are deallocated and then used later on under the assumption they"
- << "will be valid until" << pool << "has been drained.";
+@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker)
+@end
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
+#endif // QT_DEBUG
- // Reset the pool so that it's not drained again later on
- *m_pool = nullptr;
- }
+// Use the direct runtime interface to manage autorelease pools, as it
+// has less overhead then allocating NSAutoreleasePools, and allows for
+// a future where we use ARC (where NSAutoreleasePool is not allowed).
+// https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
- [super dealloc];
+extern "C" {
+void *objc_autoreleasePoolPush(void);
+void objc_autoreleasePoolPop(void *pool);
}
-@end
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
QT_BEGIN_NAMESPACE
QMacAutoReleasePool::QMacAutoReleasePool()
- : pool([[NSAutoreleasePool alloc] init])
+ : pool(objc_autoreleasePoolPush())
{
+#ifdef QT_DEBUG
+ static const bool debugAutoReleasePools = qEnvironmentVariableIsSet("QT_DARWIN_DEBUG_AUTORELEASEPOOLS");
+ if (!debugAutoReleasePools)
+ return;
+
Class trackerClass = [QMacAutoReleasePoolTracker class];
-#ifdef QT_DEBUG
void *poolFrame = nullptr;
void *frames[2];
if (backtrace_from_fp(__builtin_frame_address(0), frames, 2))
@@ -289,30 +294,14 @@ QMacAutoReleasePool::QMacAutoReleasePool()
free((char*)symbolName);
}
}
-#endif
- [[[trackerClass alloc] initWithPool:
- reinterpret_cast<NSAutoreleasePool **>(&pool)] autorelease];
+ [[trackerClass new] autorelease];
+#endif // QT_DEBUG
}
QMacAutoReleasePool::~QMacAutoReleasePool()
{
- if (!pool) {
- qWarning() << "Prematurely drained pool" << this << "finally drained. Any objects belonging"
- << "to this pool have already been released, and have potentially been invalid since the"
- << "premature drain earlier on.";
- return;
- }
-
- // Save and reset pool before draining, so that the pool tracker can know
- // that it's being drained by its owning pool.
- NSAutoreleasePool *savedPool = static_cast<NSAutoreleasePool*>(pool);
- pool = nullptr;
-
- // Drain behaves the same as release, with the advantage that
- // if we're ever used in a garbage-collected environment, the
- // drain acts as a hint to the garbage collector to collect.
- [savedPool drain];
+ objc_autoreleasePoolPop(pool);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -357,7 +346,7 @@ std::optional<uint32_t> qt_mac_sipConfiguration()
return config;
#endif
- QIOType<io_registry_entry_t> nvram = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options");
+ QIOType<io_registry_entry_t> nvram = IORegistryEntryFromPath(kIOMainPortDefault, "IODeviceTree:/options");
if (!nvram) {
qWarning("Failed to locate NVRAM entry in IO registry");
return {};
@@ -517,7 +506,7 @@ bool qt_apple_isSandboxed()
}
QT_END_NAMESPACE
-@implementation NSObject (QtSandboxHelpers)
+@implementation NSObject (QtExtras)
- (id)qt_valueForPrivateKey:(NSString *)key
{
if (qt_apple_isSandboxed())
@@ -578,6 +567,9 @@ void qt_apple_check_os_version()
#elif defined(__TV_OS_VERSION_MIN_REQUIRED)
const char *os = "tvOS";
const int version = __TV_OS_VERSION_MIN_REQUIRED;
+#elif defined(__VISION_OS_VERSION_MIN_REQUIRED)
+ const char *os = "visionOS";
+ const int version = __VISION_OS_VERSION_MIN_REQUIRED;
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
const char *os = "iOS";
const int version = __IPHONE_OS_VERSION_MIN_REQUIRED;
@@ -727,7 +719,7 @@ QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machH
};
static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk, QOperatingSystemVersion::OSType osType) {
- return qMakePair(
+ return std::pair(
QOperatingSystemVersion(osType, dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff),
QOperatingSystemVersion(osType, sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff)
);