8#include <QtCore/qprocessordetection.h>
9#include <QtCore/private/qcoreapplication_p.h>
10#include <QtCore/private/qthread_p.h>
12#include <qpa/qwindowsysteminterface.h>
14#import <Foundation/NSArray.h>
15#import <Foundation/NSString.h>
16#import <Foundation/NSProcessInfo.h>
17#import <Foundation/NSThread.h>
18#import <Foundation/NSNotification.h>
20#import <UIKit/UIApplication.h>
26#define qAlignDown(val, align) val & ~(align - 1)
27#define qAlignUp(val, align) qAlignDown(val + (align - 1), align)
83 static size_t computeSize(
size_t requestedSize)
101 struct rlimit stackLimit = {0, 0};
102 if (
Q_UNLIKELY(getrlimit(RLIMIT_STACK, &stackLimit) == 0 && stackSize > stackLimit.rlim_cur))
103 qFatal(
"Unexpectedly exceeded stack limit");
110 uintptr_t memoryStart = uintptr_t(
memory);
118 if (mprotect((
void*)memoryGuardStart,
kPageSize, PROT_READ))
119 qWarning() <<
"Failed to add memory guard:" << strerror(errno);
141 static const int kScribblePattern;
145 memset_pattern4((
void*)
limit, &kScribblePattern,
size());
150 uintptr_t highWaterMark =
limit;
151 for (; highWaterMark <
base; highWaterMark += 4) {
152 if (memcmp((
void*)highWaterMark, &kScribblePattern, 4))
156 qDebug(
"main() used roughly %lu bytes of stack space", (
base - highWaterMark));
160 const int Stack::kScribblePattern = 0xfafafafa;
164 jmp_buf processEventEnterJumpPoint;
165 jmp_buf processEventExitJumpPoint;
167 bool applicationAboutToTerminate =
false;
168 jmp_buf applicationWillTerminateJumpPoint;
170 bool debugStackUsage =
false;
187 if (
infoPlistValue(
@"QtRunLoopIntegrationDisableSeparateStack",
false))
188 requestedStackSize = 0;
190 char reservedStack[Stack::computeSize(requestedStackSize)];
192 if (
sizeof(reservedStack) > 0) {
193 userMainStack.adopt(reservedStack,
sizeof(reservedStack));
195 if (
infoPlistValue(
@"QtRunLoopIntegrationDebugStackUsage",
false)) {
196 debugStackUsage =
true;
197 userMainStack.scribble();
198 qDebug(
"Effective stack size is %lu bytes", userMainStack.size());
203 lcEventDispatcher().isDebugEnabled(),
"UIApplicationMain").enter();
205 qCDebug(lcEventDispatcher) <<
"Running UIApplicationMain";
218extern "C" int main(
int argc,
char *argv[]);
224 char **argv =
new char*[argc];
226 for (
int i = 0;
i < argc; ++
i) {
229 NSStringEncoding cStringEncoding = [NSString defaultCStringEncoding];
230 unsigned int bufferSize = [
arg lengthOfBytesUsingEncoding:cStringEncoding] + 1;
231 argv[
i] =
reinterpret_cast<char *
>(malloc(bufferSize));
234 qFatal(
"Could not convert argv[%d] to C string",
i);
237 int exitCode =
main(argc, argv);
240 logActivity.applicationDidFinishLaunching.enter();
241 qCDebug(lcEventDispatcher) <<
"Returned from main with exit code " << exitCode;
244 userMainStack.printUsage();
246 logActivity.applicationDidFinishLaunching.leave();
248 if (applicationAboutToTerminate)
262 return userMainStack.isValid();
272 [[NSNotificationCenter defaultCenter]
274 selector:@selector(applicationDidFinishLaunching:)
275 name:UIApplicationDidFinishLaunchingNotification
278 [[NSNotificationCenter defaultCenter]
280 selector:@selector(applicationWillTerminate)
281 name:UIApplicationWillTerminateNotification
285#if defined(Q_PROCESSOR_X86)
286# define FUNCTION_CALL_ALIGNMENT 16
287# if defined(Q_PROCESSOR_X86_32)
288# define SET_STACK_POINTER "mov %0, %%esp"
289# elif defined(Q_PROCESSOR_X86_64)
290# define SET_STACK_POINTER "movq %0, %%rsp"
292#elif defined(Q_PROCESSOR_ARM)
294# define FUNCTION_CALL_ALIGNMENT 4
295# define SET_STACK_POINTER "mov sp, %0"
297# error "Unknown processor family"
300+ (
void)applicationDidFinishLaunching:(NSNotification *)notification
303 lcEventDispatcher().isDebugEnabled(),
"applicationDidFinishLaunching", logActivity.UIApplicationMain).enter();
305 qCDebug(lcEventDispatcher) <<
"Application launched with options" << notification.userInfo;
314 qCDebug(lcEventDispatcher) <<
"Scheduling main() on next run-loop pass";
315 CFRunLoopTimerRef userMainTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault,
316 CFAbsoluteTimeGetCurrent(), 0, 0, 0, ^(CFRunLoopTimerRef) { user_main_trampoline(); });
317 CFRunLoopAddTimer(CFRunLoopGetMain(), userMainTimer, kCFRunLoopCommonModes);
318 CFRelease(userMainTimer);
322 switch (setjmp(processEventEnterJumpPoint)) {
324 qCDebug(lcEventDispatcher) <<
"Running main() on separate stack";
331 __asm__ __volatile__(
334 :
"r" (
qAlignDown(userMainStack.base, FUNCTION_CALL_ALIGNMENT))
337 user_main_trampoline();
345 logActivity.UIApplicationMain.enter();
346 qCDebug(lcEventDispatcher) <<
"↳ Jumped from processEvents due to exec";
349 userMainStack.printUsage();
353 qFatal(
"Unexpected jump result in event loop integration");
362+ (
void)applicationWillTerminate
365 lcEventDispatcher().isDebugEnabled(),
"applicationWillTerminate", logActivity.UIApplicationMain).enter();
366 qCDebug(lcEventDispatcher) <<
"Application about to be terminated by iOS";
383 applicationAboutToTerminate =
true;
384 switch (setjmp(applicationWillTerminateJumpPoint)) {
386 qCDebug(lcEventDispatcher) <<
"Exiting qApp with SIGTERM exit code";
392 qCDebug(lcEventDispatcher) <<
"Manually triggering return from event loop exec";
393 applicationWillTerminateActivity.
leave();
397 applicationWillTerminateActivity.
enter();
399 qCDebug(lcEventDispatcher) <<
"kJumpedFromUserMainTrampoline, allowing iOS to terminate";
400 applicationWillTerminateActivity.
leave();
403 qFatal(
"Unexpected jump result in event loop integration");
440 QEventLoop::ProcessEventsFlags
flags
442 qCDebug(lcEventDispatcher) <<
"Sending window system events for" <<
flags;
450 , m_processEventLevel(0)
457 if (applicationAboutToTerminate) {
458 qCDebug(lcEventDispatcher) <<
"Detected QEventLoop exec after application termination";
466 qCDebug(lcEventDispatcher) <<
"Processing events with flags" <<
flags;
468 ++m_processEventLevel;
470 m_runLoopExitObserver.
addToMode(kCFRunLoopCommonModes);
474 switch (setjmp(processEventExitJumpPoint)) {
476 qCDebug(lcEventDispatcher) <<
"QEventLoop exec detected, jumping back to system runloop ↵";
484 qCDebug(lcEventDispatcher) <<
"⇢ System runloop exited, returning with eventsProcessed = true";
487 qFatal(
"Unexpected jump result in event loop integration");
493 ++m_processEventLevel;
495 --m_processEventLevel;
497 return processedEvents;
503 Q_ASSERT(activity == kCFRunLoopExit);
513 --m_processEventLevel;
520 switch (setjmp(processEventEnterJumpPoint)) {
522 qCDebug(lcEventDispatcher) <<
"Jumping into processEvents due to system runloop exit ⇢";
523 logActivity.UIApplicationMain.leave();
528 logActivity.UIApplicationMain.enter();
529 qCDebug(lcEventDispatcher) <<
"↳ Jumped from processEvents due to re-exec";
532 qFatal(
"Unexpected jump result in event loop integration");
QAppleLogActivity && enter()
T loadRelaxed() const noexcept
virtual bool processPostedEvents()
ProcessEventsState m_processEvents
bool processEvents(QEventLoop::ProcessEventsFlags flags) override
Processes pending events that match flags until there are no more events to process.
QEventLoop * currentEventLoop() const
bool processPostedEvents() override
Override of the CoreFoundation posted events runloop source callback so that we can send window syste...
QIOSEventDispatcher(QObject *parent=nullptr)
static QIOSEventDispatcher * create()
QIOSJumpingEventDispatcher(QObject *parent=nullptr)
void interruptEventLoopExec()
bool processEvents(QEventLoop::ProcessEventsFlags flags) override
Processes pending events that match flags until there are no more events to process.
void handleRunLoopExit(CFRunLoopActivity activity)
qsizetype count() const noexcept
static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
static void setSynchronousWindowSystemEvents(bool enable)
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
void removeFromMode(CFStringRef mode, CFRunLoopRef runLoop=0)
QList< QVariant > arguments
Combined button and popup list for selecting options.
#define QT_APPLE_SCOPED_LOG_ACTIVITY(...)
#define QT_APPLE_LOG_ACTIVITY(...)
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static const size_t kBytesPerKiloByte
#define qAlignUp(val, align)
#define qAlignDown(val, align)
int qt_main_wrapper(int argc, char *argv[])
static const char kApplicationWillTerminateExitCode
@ kJumpPointSetSuccessfully
@ kJumpedFromUserMainTrampoline
@ kJumpedFromEventLoopExecInterrupt
@ kJumpedFromEventDispatcherProcessEvents
static bool rootLevelRunLoopIntegration()
static const long kPageSize
int infoPlistValue(NSString *key, int defaultValue)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum GLsizei GLsizei GLuint memory
QT_END_NAMESPACE typedef QT_PREPEND_NAMESPACE(quintptr) WId
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent