diff --git a/darwin/main.m b/darwin/main.m index 72dd704a..9b6010b0 100644 --- a/darwin/main.m +++ b/darwin/main.m @@ -1,5 +1,4 @@ // 20 april 2019 -#import #import "uipriv_darwin.h" @interface uiprivApplication : NSApplication @@ -50,11 +49,10 @@ const char **uiprivSysInitErrors(void) } static pthread_t mainThread; +static BOOL initialized = NO; // TODO deduplicate this from common/init.c int uiprivSysInit(void *options, uiInitError *err) { - int lockerr; - uiprivApp = [uiprivApplication sharedApplication]; if (![NSApp isKindOfClass:[uiprivApplication class]]) return uiprivInitReturnError(err, errNSAppAlreadyInitialized); @@ -67,16 +65,21 @@ int uiprivSysInit(void *options, uiInitError *err) [uiprivApp setDelegate:uiprivAppDelegate]; mainThread = pthread_self(); + initialized = YES; return 1; } void uiMain(void) { + if (!uiprivCheckInitializedAndThread()) + return; [uiprivApp run]; } void uiQuit(void) { + if (!uiprivCheckInitializedAndThread()) + return; @autoreleasepool { NSEvent *e; @@ -99,6 +102,10 @@ void uiQuit(void) // thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch for this void uiQueueMain(void (*f)(void *data), void *data) { + if (!initialized) { + uiprivProgrammerError(uiprivProgrammerErrorNotInitialized, uiprivFunc); + return; + } // dispatch_get_main_queue() is a serial queue so it will not execute multiple uiQueueMain() functions concurrently // the signature of f matches dispatch_function_t dispatch_async_f(dispatch_get_main_queue(), data, f); diff --git a/darwin/uipriv_darwin.h b/darwin/uipriv_darwin.h index 4a089dde..c5ee1138 100644 --- a/darwin/uipriv_darwin.h +++ b/darwin/uipriv_darwin.h @@ -4,6 +4,8 @@ #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_8 #import #import // see future.m +#import +#import #import "../ui.h" #import "../ui_darwin.h" #import "../common/uipriv.h" diff --git a/test/allcalls.h b/test/allcalls.h index 36966859..10cf592e 100644 --- a/test/allcalls.h +++ b/test/allcalls.h @@ -1,3 +1,13 @@ // 28 may 2019 // This file should NOT have include guards as it is intended to be included more than once; see noinitwrongthread.c for details. + +allcallsCase(uiMain, /* no arguments */) +allcallsCase(uiQuit, /* no arguments */) + +allcallsCase(uiNewEvent, NULL) +allcallsCase(uiEventAddHandler, NULL, NULL, NULL, NULL) +allcallsCase(uiEventDeleteHandler, NULL, 0) +allcallsCase(uiEventFire, NULL, NULL, NULL) +allcallsCase(uiEventHandlerBlocked, NULL, 0) +allcallsCase(uiEventSetHandlerBlocked, NULL, 0, false) diff --git a/test/noinitwrongthread.c b/test/noinitwrongthread.c index 0b5db00b..0671ec95 100644 --- a/test/noinitwrongthread.c +++ b/test/noinitwrongthread.c @@ -1,4 +1,6 @@ // 28 may 2019 +#include +#include "lib/thread.h" #include "test.h" struct errorCase { @@ -68,7 +70,7 @@ static void freeCases(struct errorCase *first) static void reportCases(testingT *t, struct errorCase *p) { while (p != NULL) { - testingTLogf(t, "*** %s", t->name); + testingTLogf(t, "*** %s", p->name); if (!p->caught) { testingTErrorf(t, "%s did not throw a programmer error; should have", p->name); p = p->next; @@ -91,7 +93,7 @@ static void reportCases(testingT *t, struct errorCase *p) return first; \ current->name = #f "()"; \ current->msgWant = "attempt to call " #f "() " allcallsMsgSuffix; \ - f(__VA_LIST__); \ + f(__VA_ARGS__); \ if (first == NULL) \ first = current; \ if (last != NULL) \