Skip to content

Commit d4641ec

Browse files
committed
Trying to fix a range of crashes when closing a connection window
Caused by a use-after-free of an unretained ivar
1 parent 80f8cae commit d4641ec

File tree

5 files changed

+48
-6
lines changed

5 files changed

+48
-6
lines changed

Source/SPDatabaseDocument.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6290,6 +6290,7 @@ - (void)_processDatabaseChangedBundleTriggerActions
62906290

62916291
- (void)dealloc
62926292
{
6293+
NSAssert([NSThread isMainThread], @"Calling %s from a background thread is not supported!",__func__);
62936294
#ifndef SP_CODA /* Unregister observers */
62946295
// Unregister observers
62956296
[prefs removeObserver:self forKeyPath:SPDisplayTableViewVerticalGridlines];

Source/SPFunctions.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
//
2929
// More info at <https://github.com/sequelpro/sequelpro>
3030

31-
31+
/**
32+
* Synchronously execute a block on the main thread.
33+
* This function can be called from a background thread as well as from
34+
* the main thread.
35+
*/
3236
void SPMainQSync(void (^block)(void));
3337

Source/SPWindowController.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,17 @@
4949
// Database connection management
5050
- (IBAction)addNewConnection:(id)sender;
5151
- (IBAction)moveSelectedTabInNewWindow:(id)sender;
52+
53+
/**
54+
* @danger THIS IS NOT RETAINED!!!
55+
*
56+
* Ever only directly use it on the main thread!
57+
* Do not cache it without retaining first!
58+
* For background threads get it and retain it via the main thread!
59+
* Release it on the main thread again.
60+
*/
5261
- (SPDatabaseDocument *)selectedTableDocument;
62+
5363
- (void)updateSelectedTableDocument;
5464
- (void)updateAllTabTitles:(id)sender;
5565
- (IBAction)closeTab:(id)sender;

Source/SPWindowController.m

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ - (void)_setUpTabBar;
5353
- (void)_updateProgressIndicatorForItem:(NSTabViewItem *)theItem;
5454
- (void)_createTitleBarLineHidingView;
5555
- (void)_updateLineHidingViewState;
56-
56+
- (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc;
57+
- (void)_selectedTableDocumentDeallocd:(NSNotification *)notification;
5758
@end
5859

5960
@implementation SPWindowController
@@ -63,7 +64,7 @@ @implementation SPWindowController
6364

6465
- (void)awakeFromNib
6566
{
66-
selectedTableDocument = nil;
67+
[self _switchOutSelectedTableDocument:nil];
6768

6869
[[self window] setCollectionBehavior:[[self window] collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary];
6970

@@ -141,7 +142,7 @@ - (SPDatabaseDocument *)selectedTableDocument
141142
*/
142143
- (void)updateSelectedTableDocument
143144
{
144-
selectedTableDocument = [[tabView selectedTabViewItem] identifier];
145+
[self _switchOutSelectedTableDocument:[[tabView selectedTabViewItem] identifier]];
145146

146147
[selectedTableDocument didBecomeActiveTabInWindow];
147148
}
@@ -388,7 +389,7 @@ - (NSMethodSignature *)methodSignatureForSelector:(SEL)theSelector
388389
*/
389390
- (BOOL)respondsToSelector:(SEL)theSelector
390391
{
391-
return ([super respondsToSelector:theSelector] || (selectedTableDocument && [selectedTableDocument respondsToSelector:theSelector]));
392+
return ([super respondsToSelector:theSelector] || [selectedTableDocument respondsToSelector:theSelector]);
392393
}
393394

394395
/**
@@ -529,10 +530,35 @@ - (void)_updateLineHidingViewState
529530
}
530531
}
531532

533+
534+
- (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc
535+
{
536+
NSAssert([NSThread isMainThread], @"Switching the selectedTableDocument via a background thread is not supported!");
537+
538+
// shortcut if there is nothing to do
539+
if(selectedTableDocument == newDoc) return;
540+
541+
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
542+
if(selectedTableDocument) {
543+
[nc removeObserver:self name:SPDocumentWillCloseNotification object:selectedTableDocument];
544+
selectedTableDocument = nil;
545+
}
546+
if(newDoc) {
547+
[nc addObserver:self selector:@selector(_selectedTableDocumentDeallocd:) name:SPDocumentWillCloseNotification object:newDoc];
548+
selectedTableDocument = newDoc;
549+
}
550+
}
551+
552+
- (void)_selectedTableDocumentDeallocd:(NSNotification *)notification
553+
{
554+
[self _switchOutSelectedTableDocument:nil];
555+
}
556+
532557
#pragma mark -
533558

534559
- (void)dealloc
535560
{
561+
[self _switchOutSelectedTableDocument:nil];
536562
[[NSNotificationCenter defaultCenter] removeObserver:self];
537563

538564
[NSObject cancelPreviousPerformRequestsWithTarget:self];

Source/SPWindowControllerDelegate.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ @interface SPWindowController (SPDeclaredAPI)
4141

4242
- (void)_updateProgressIndicatorForItem:(NSTabViewItem *)theItem;
4343
- (void)_updateLineHidingViewState;
44+
- (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc;
4445

4546
@end
4647

@@ -186,7 +187,7 @@ - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabVi
186187
{
187188
if ([[PSMTabDragAssistant sharedDragAssistant] isDragging]) return;
188189

189-
selectedTableDocument = [tabViewItem identifier];
190+
[self _switchOutSelectedTableDocument:[tabViewItem identifier]];
190191
[selectedTableDocument didBecomeActiveTabInWindow];
191192

192193
if ([[self window] isKeyWindow]) [selectedTableDocument tabDidBecomeKey];

0 commit comments

Comments
 (0)