Crash on macOS 10.14 (Mojave) with SDL_ShowMessageBox

OS upgrades are always wonderful, but breaking code isn’t. I’ve run into an unfortunate issue where my program crashes upon a call for SDL_ShowMessageBox. I get the following output in terminal:

2018-10-02 20:29:10.765 oneshot[28230:6676460] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSWindow drag regions should only be invalidated on the Main Thread!'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff3eb2843d __exceptionPreprocess + 256
	1   libobjc.A.dylib                     0x00007fff6aa39720 objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff3eb41ec1 -[NSException raise] + 9
	3   AppKit                              0x00007fff3c0462a5 -[NSWindow(NSWindow_Theme) _postWindowNeedsToResetDragMarginsUnlessPostingDisabled] + 324
	4   AppKit                              0x00007fff3c04368c -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1488
	5   AppKit                              0x00007fff3c103edf -[NSPanel _initContent:styleMask:backing:defer:contentView:] + 50
	6   AppKit                              0x00007fff3c0430b6 -[NSWindow initWithContentRect:styleMask:backing:defer:] + 45
	7   AppKit                              0x00007fff3c103e94 -[NSPanel initWithContentRect:styleMask:backing:defer:] + 64
	8   AppKit                              0x00007fff3c0415c7 -[NSWindowTemplate nibInstantiate] + 495
	9   AppKit                              0x00007fff3bfbc646 -[NSIBObjectData instantiateObject:] + 267
	10  AppKit                              0x00007fff3bfbb9b4 -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 579
	11  AppKit                              0x00007fff3bfb9be1 loadNib + 401
	12  AppKit                              0x00007fff3bfb90a9 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:options:withZone:ownerBundle:] + 696
	13  AppKit                              0x00007fff3bfb8cee -[NSBundle(NSNibLoading) loadNibNamed:owner:topLevelObjects:] + 204
	14  AppKit                              0x00007fff3c372cc9 -[NSAlert init] + 101
	15  libSDL2-2.0.0.dylib                 0x000000010a36287b Cocoa_ShowMessageBox + 75
	16  libSDL2-2.0.0.dylib                 0x000000010a33d049 SDL_ShowMessageBox_REAL + 393
	17  oneshot                             0x0000000109fd3117 _ZN7Oneshot6msgboxEiPKcS1_ + 231
	18  oneshot                             0x0000000109fe6d4d _ZL13oneshotMsgBoxiPmm + 461
	19  libruby.2.5.dylib                   0x000000010a5dc481 vm_call_cfunc + 283
	20  libruby.2.5.dylib                   0x000000010a5cc5c7 vm_exec_core + 11481
	21  libruby.2.5.dylib                   0x000000010a5d8b11 vm_exec + 142
	22  libruby.2.5.dylib                   0x000000010a5d7f96 vm_invoke_proc + 268
	23  libruby.2.5.dylib                   0x000000010a5b0f64 thread_start_func_2 + 1316
	24  libruby.2.5.dylib                   0x000000010a5b0a37 thread_start_func_1 + 69
	25  libsystem_pthread.dylib             0x00007fff6bcf933d _pthread_body + 126
	26  libsystem_pthread.dylib             0x00007fff6bcfc2a7 _pthread_start + 70
	27  libsystem_pthread.dylib             0x00007fff6bcf8425 thread_start + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

This didn’t occur in High Sierra (10.13). I tried the 2.0.8 release, as well as the current development branch, however neither worked. The code that calls this function can be found here.

Thank you in advance!

Apple only allows native UI functionality to be used on the main thread in macOS and iOS. It sounds like they have more robust runtime checks for that in 10.14, which is probably a good thing if the alternative is hard-to-diagnose glitches and crashes due to memory corruption etc.

See also: https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

Ouch, thank you for the response – this will require some hard studying to figure out how to pull this off properly. Unfortunately most of the code I’m playing with is dimensions beyond me, but fingers crossed that I’ll be able to get it functioning. :stuck_out_tongue:

The docs of SDL_ShowMessageBox() say “This function should be called on the thread that created the parent window, or on the main thread if the messagebox has no parent”. I’m unclear whether this is compatible with what Apple requires or not; if it isn’t I foresee problems!

The statement is luckily more than compatible, now it’s more that on macOS it must be called from the main thread, or have it wrapped in a dispatch_queue statement (which is the solution I’ve chosen). Though it might be a good idea to possibly update the docs to reflect this OS update or something?

But is “the thread that created the parent window” necessarily the same as the “main thread”, and if so why do the docs make a distinction between them?

There is no similar warning for SDL_ShowSimpleMessageBox(), indeed it specifically states that “This function may be called at any time”, so hopefully that remains the case and it isn’t affected by any thread constraints imposed by Apple.

All message box functions use Apple’s native UI so they share the threading constraints that Apple’s UI has.

The “may be called at any time” part of the documentation is in the context of the video subsystem - it can be called before that has been initialized, and after it has been quit.

If there was a thread constraint I would expect the docs to say so (as they do in the case of SDL_ShowMessageBox), but they don’t. My understanding is that SDL_ShowSimpleMessageBox is specifically intended to be used anywhere, as the docs say, including in any thread - the whole point being to have a means of reporting a message whatever the circumstances.

If Apple’s native UI imposes a thread constraint, it should in my opinion be the responsibility of SDL to use an alternative mechanism to display the message box that bypasses that limitation (I think on some platforms it already rolls its own box). What’s the point of an ‘abstraction layer’ if it doesn’t ‘abstract’?!