Issue with shutdownNSApp if shutdown is initiated from a signal handler

As soon as i started to hook the JUCEApplication shutdown from a signal handler, i started getting this crash:

2022-03-23 09:04:02.943 repro[59410:968320] *** Assertion failure in +[NSEvent startPeriodicEventsAfterDelay:withPeriod:], NSEvent.m:4431
2022-03-23 09:04:02.963 repro[59410:968320] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Periodic events are already being generated'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff205761db __exceptionPreprocess + 242
	1   libobjc.A.dylib                     0x00007fff202afd92 objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff2059f352 +[NSException raise:format:arguments:] + 88
	3   Foundation                          0x00007fff2135e4d2 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
	4   AppKit                              0x00007fff232c4b77 +[NSEvent startPeriodicEventsAfterDelay:withPeriod:] + 338
	5   repro                               0x0000000104f11d7e _ZN4juceL13shutdownNSAppEv + 62
	6   repro                               0x0000000104f073bd _ZN4juce14MessageManager16stopDispatchLoopEv + 61
	7   repro                               0x0000000104f07321 _ZN4juce19JUCEApplicationBase4quitEv + 17
	8   repro                               0x0000000104c75628 _ZN7repro11Application19systemRequestedQuitEv + 392
	9   repro                               0x0000000104c6e881 _ZN7repro13signalHandlerEi + 401
	10  libsystem_platform.dylib            0x00007fff20449d7d _sigtramp + 29

So i added an explicit stopPeriodicEvents
before startPeriodicEventsAfterDelay and any issue disappeared.

static void shutdownNSApp()
{
    [NSApp stop: nil];

    [NSEvent stopPeriodicEvents]; // < add this
    [NSEvent startPeriodicEventsAfterDelay: 0  withPeriod: 0.1];
}

I think it’s probably a bad idea to call NSApp stop from a signal handler at all.

The man page for sigaction gives a list of functions that are safe to call from a signal handler, and then says:

All functions not in the above lists are considered to be unsafe with respect to signals. That is to say, the behaviour of such functions when called from a signal handler is undefined. In general though, signal handlers should do little more than set a flag; most other actions are not safe.

I’d recommend using this approach (setting a flag and checking it periodically on the message thread) instead.

i thought that calling JUCEApplication::quit was a hardened call possible to do it safely from any thread / signal.

It will be much more efficient to handle the flag in the message loop than having a dedicated thread or even worse a timer to poll the flag for exiting.