Skip to content

Commit 04a7782

Browse files
committed
Skip Preferences close work during app terminate
PreferencesController.handleWillClose: runs read_config_file, machine reselection, scaler hotswap, [machineRomsController setContent:nil], and [machineRoms release] alongside removing its NSWindowWillCloseNotification observer. When [NSApp terminate:] cascade-closes the windows with Preferences still open, the WillClose notification fires the handler and one of those teardowns reaches into NSWindow's notification observer table while it is still being walked. _platform_strcmp segfaults inside __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__. Latent in the runModal era: the modal session blocked Cmd+Q delivery, so the user could not quit with Preferences open. Removing runModal reaches this path. Register a class-target observer for NSApplicationWillTerminateNotification (which fires before the close cascade), set a file-static flag, and short-circuit handleWillClose: when it is set. Settings have already been persisted to NSUserDefaults via the binding chain by the time the user clicks Quit, so the work being skipped is the apply-back path: meaningless at exit and dangerous when invoked from inside the terminate cascade.
1 parent 5eaed9a commit 04a7782

1 file changed

Lines changed: 28 additions & 0 deletions

File tree

fusepb/controllers/PreferencesController.m

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,32 @@
6060

6161
@implementation PreferencesController
6262

63+
/* Set on NSApplicationWillTerminateNotification so handleWillClose:
64+
can skip the settings-apply / KVO-teardown work when the close is
65+
part of [NSApp terminate:]'s cascade. Touching NSArrayController
66+
content or driving graphics hotswaps from inside that cascade
67+
reaches the notification observer table while NSWindow is still
68+
walking it, producing the strcmp crash in
69+
__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__. The work
70+
skipped here only matters when the emulator continues running
71+
after the window closes; at quit time the settings have already
72+
been persisted to NSUserDefaults via the binding chain. */
73+
static BOOL appTerminating = NO;
74+
75+
+ (void)load
76+
{
77+
[[NSNotificationCenter defaultCenter]
78+
addObserver:self
79+
selector:@selector(handleAppWillTerminate:)
80+
name:NSApplicationWillTerminateNotification
81+
object:nil];
82+
}
83+
84+
+ (void)handleAppWillTerminate:(NSNotification *)note
85+
{
86+
appTerminating = YES;
87+
}
88+
6389
+(void) initialize
6490
{
6591
ScalerNameToIdTransformer *sNToITransformer;
@@ -225,6 +251,8 @@ - (void)handleWillClose:(NSNotification *)note
225251
{
226252
[[NSNotificationCenter defaultCenter] removeObserver:self];
227253

254+
if( appTerminating ) return;
255+
228256
int old_bilinear = settings_current.bilinear_filter;
229257
int old_joy1_number = settings_current.joy1_number;
230258
int old_joy2_number = settings_current.joy2_number;

0 commit comments

Comments
 (0)