XQuartz: Detect FatalErrors on startup to prevent tight crash loops

If a FatalError occurs before the server finishes launching, it will
not have drained the launchd-owned DISPLAY socket, so launchd will
just relaunch it.  This can cause the server to crash in a tight loop
which will spam the user with CrashReporter windows that claim focus on
appearance.

This allows users stuck in this loop to "deal" with the problem without
popping up a crash report every 10 seconds.

Signed-off-by: Jeremy Huddleston <jeremyhu@apple.com>
This commit is contained in:
Jeremy Huddleston 2012-02-17 13:15:12 -08:00
parent a818b30598
commit 3505e1faad
4 changed files with 51 additions and 1 deletions

View File

@ -108,6 +108,9 @@ X11ApplicationCanEnterRandR(void);
void
X11ApplicationMain(int argc, char **argv, char **envp);
void
X11ApplicationFatalError(const char *f, va_list args) __printflike(1, 0);
#define PREFS_APPSMENU "apps_menu"
#define PREFS_FAKEBUTTONS "enable_fake_buttons"
#define PREFS_KEYEQUIVS "enable_key_equivalents"

View File

@ -70,6 +70,7 @@ static dispatch_queue_t eventTranslationQueue;
extern Bool noTestExtensions;
extern Bool noRenderExtension;
extern BOOL serverRunning;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
static TISInputSourceRef last_key_layout;
@ -1067,6 +1068,50 @@ NO] || XQuartzShieldingWindowLevel != 0)
}
}
void
X11ApplicationFatalError(const char *f, va_list args)
{
#ifdef HAVE_LIBDISPATCH
NSString *title, *msg;
char *error_msg;
/* This is called by FatalError() in the server thread just before
* we would abort. If the server never got off the ground, We should
* inform the user of the error rather than letting the ever-so-friendly
* CrashReporter do it for us.
*
* This also has the benefit of forcing user interaction rather than
* allowing an infinite throttled-restart if the crash occurs before
* we can drain the launchd socket.
*/
if (serverRunning) {
return;
}
title = NSLocalizedString(@"The application X11 could not be opened.",
@"Dialog title when encountering a fatal error");
msg = NSLocalizedString(@"An error occurred while starting the X11 server: \"%s\"\n\nClick Quit to quit X11. Click Report to see more details or send a report to Apple.",
@"Dialog when encountering a fatal error");
vasprintf(&error_msg, f, args);
msg = [NSString stringWithFormat:msg, error_msg];
/* We want the AppKit thread to actually service the alert or we will race [NSApp run] and create an
* 'NSInternalInconsistencyException', reason: 'NSApp with wrong _running count'
*/
dispatch_sync(dispatch_get_main_queue(), ^{
if (NSAlertDefaultReturn == NSRunAlertPanel(title, msg, NSLocalizedString(@"Quit", @""),
NSLocalizedString (@"Report...", @""), nil)) {
exit(EXIT_FAILURE);
}
});
/* fall back to caller to do the abort() in the DIX */
#endif
}
static void
check_xinitrc(void)
{

View File

@ -78,6 +78,8 @@
#include "quartzKeyboard.h"
#include "quartz.h"
#include "X11Application.h"
aslclient aslc;
void
@ -636,7 +638,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
void
OsVendorFatalError(const char *f, va_list args)
{
ErrorF(" OsVendorFatalError\n");
X11ApplicationFatalError(f, args);
}
/*