aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2010-03-31 23:35:06 +0000
committerrowanbeentje <rowan@beent.je>2010-03-31 23:35:06 +0000
commit06e417594cd0fcdede2f0713c63a861bc65d7e99 (patch)
treede21be7bf852ec3a03c9baf2535ce4cebb5d0cdd
parent836b96f7e1481938c0267448b940b5d8e202eb09 (diff)
downloadsequelpro-06e417594cd0fcdede2f0713c63a861bc65d7e99.tar.gz
sequelpro-06e417594cd0fcdede2f0713c63a861bc65d7e99.tar.bz2
sequelpro-06e417594cd0fcdede2f0713c63a861bc65d7e99.zip
- Improve SPSSHTunnel question/password dialogs to no longer eat 100% CPU by switching from NSCondition blocking to NSLock blocking
- Improve behaviour of SSH tunnels with no password in keychain - prompt appropriately - Set MXPConnection to check the proxy state when attempting to reconnect a dropped connection, extending the timer when an auth UI is up. This prevents a multiple-dialogs misbehaviour (or sometimes deadlock), addressing the last part of http://log.sequelpro.com/view/86 .
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m7
-rw-r--r--Source/SPConnectionController.m2
-rw-r--r--Source/SPSSHTunnel.h3
-rw-r--r--Source/SPSSHTunnel.m59
4 files changed, 40 insertions, 31 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
index 7571cd0e..555f87dc 100644
--- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
@@ -476,7 +476,7 @@ static BOOL sTruncateLongFieldInLogs = YES;
eventLoopStartDate = [NSDate date];
[[NSRunLoop currentRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
if ([[NSDate date] timeIntervalSinceDate:eventLoopStartDate] < 0.25) {
- usleep(250000 - (100000 * [[NSDate date] timeIntervalSinceDate:eventLoopStartDate]));
+ usleep(250000 - (1000000 * [[NSDate date] timeIntervalSinceDate:eventLoopStartDate]));
}
}
@@ -505,7 +505,10 @@ static BOOL sTruncateLongFieldInLogs = YES;
if ([[NSDate date] timeIntervalSinceDate:interfaceInteractionTimer] > 0.25) {
proxyStartDate = [proxyStartDate addTimeInterval:([[NSDate date] timeIntervalSinceDate:interfaceInteractionTimer] - 0.25)];
} else {
- usleep(250000 - (100000 * [[NSDate date] timeIntervalSinceDate:interfaceInteractionTimer]));
+ usleep(250000 - (1000000 * [[NSDate date] timeIntervalSinceDate:interfaceInteractionTimer]));
+ if ([connectionProxy state] == PROXY_STATE_WAITING_FOR_AUTH) {
+ proxyStartDate = [proxyStartDate addTimeInterval:0.26];
+ }
}
}
diff --git a/Source/SPConnectionController.m b/Source/SPConnectionController.m
index 0281896f..ecfd6bc4 100644
--- a/Source/SPConnectionController.m
+++ b/Source/SPConnectionController.m
@@ -706,6 +706,7 @@
connectionKeychainItemAccount = [[keychain accountForUser:[self valueForKeyPath:@"selectedFavorite.user"] host:(([self type] == SPSocketConnection)?@"localhost":[self valueForKeyPath:@"selectedFavorite.host"]) database:[self valueForKeyPath:@"selectedFavorite.database"]] retain];
[self setPassword:[keychain getPasswordForName:connectionKeychainItemName account:connectionKeychainItemAccount]];
if (![[self password] length]) {
+ [self setPassword:nil];
[connectionKeychainItemName release], connectionKeychainItemName = nil;
[connectionKeychainItemAccount release], connectionKeychainItemAccount = nil;
}
@@ -715,6 +716,7 @@
connectionSSHKeychainItemAccount = [[keychain accountForSSHUser:[self valueForKeyPath:@"selectedFavorite.sshUser"] sshHost:[self valueForKeyPath:@"selectedFavorite.sshHost"]] retain];
[self setSshPassword:[keychain getPasswordForName:connectionSSHKeychainItemName account:connectionSSHKeychainItemAccount]];
if (![[self sshPassword] length]) {
+ [self setSshPassword:nil];
[connectionSSHKeychainItemName release], connectionSSHKeychainItemName = nil;
[connectionSSHKeychainItemAccount release], connectionSSHKeychainItemAccount = nil;
}
diff --git a/Source/SPSSHTunnel.h b/Source/SPSSHTunnel.h
index 45f513ec..27522d90 100644
--- a/Source/SPSSHTunnel.h
+++ b/Source/SPSSHTunnel.h
@@ -61,8 +61,7 @@
NSInteger localPortFallback;
NSInteger connectionState;
- BOOL isAnswerAvailable;
- NSCondition *answerAvailableCondition;
+ NSLock *answerAvailableLock;
NSString *currentKeyName;
}
diff --git a/Source/SPSSHTunnel.m b/Source/SPSSHTunnel.m
index 46ceea97..207dc300 100644
--- a/Source/SPSSHTunnel.m
+++ b/Source/SPSSHTunnel.m
@@ -27,6 +27,7 @@
#import "RegexKitLite.h"
#import "SPKeychain.h"
#import "SPConstants.h"
+#import "SPMainThreadTrampoline.h"
#import <netinet/in.h>
@@ -55,6 +56,7 @@
stateChangeSelector = nil;
lastError = nil;
debugMessages = [[NSMutableArray alloc] init];
+ answerAvailableLock = [[NSLock alloc] init];
// Set up a connection for use by the tunnel process
tunnelConnectionName = [[NSString alloc] initWithFormat:@"SequelPro-%lu", (unsigned long)[[NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]] hash]];
@@ -137,6 +139,14 @@
*/
- (NSInteger) state
{
+
+ // See if an auth dialog is up
+ if (![answerAvailableLock tryLock]) {
+ return PROXY_STATE_WAITING_FOR_AUTH;
+ }
+ [answerAvailableLock unlock];
+
+ // Return the currently recorded state
return connectionState;
}
@@ -467,21 +477,20 @@
*/
- (BOOL) getResponseForQuestion:(NSString *)theQuestion
{
- // prepare the condition
- [answerAvailableCondition lock];
- isAnswerAvailable = NO;
+ // Lock the answer available lock
+ [[answerAvailableLock onMainThread] lock];
- // request an answer on the main thread (UI stuff must be done on main thread)
+ // Request an answer on the main thread (UI stuff must be done on main thread)
[self performSelectorOnMainThread:@selector(workerGetResponseForQuestion:) withObject:theQuestion waitUntilDone:YES];
- // wait for the signal in closeSSHQuestionSheet:
- while (!isAnswerAvailable) [answerAvailableCondition wait];
+ // Wait for closeSSHQuestionSheet: to unlock the lock, indicating an answer is available
+ while (![answerAvailableLock tryLock]) usleep(25000);
- // save the answer
+ // Save the answer
BOOL response = requestedResponse;
- //unlock condition
- [answerAvailableCondition unlock];
+ // Unlock the lock again
+ [answerAvailableLock unlock];
//return the answer
return response;
@@ -507,13 +516,10 @@
*/
- (IBAction) closeSSHQuestionSheet:(id)sender
{
- [answerAvailableCondition lock];
requestedResponse = [sender tag]==1 ? YES : NO;
[NSApp endSheet:sshQuestionDialog];
[sshQuestionDialog orderOut:nil];
- isAnswerAvailable = YES;
- [answerAvailableCondition signal];
- [answerAvailableCondition unlock];
+ [[answerAvailableLock onMainThread] unlock];
}
/*
@@ -524,27 +530,26 @@
{
if (![theHash isEqualToString:tunnelConnectionVerifyHash]) return nil;
- // prepare the condition
- [answerAvailableCondition lock];
- isAnswerAvailable = NO;
+ // Lock the answer available lock
+ [[answerAvailableLock onMainThread] lock];
- // request password on the main thread (UI stuff must be done on main thread)
+ // Request password on the main thread (UI stuff must be done on main thread)
[self performSelectorOnMainThread:@selector(workerGetPasswordForQuery:) withObject:theQuery waitUntilDone:YES];
- // wait for the signal in closeSSHPasswordSheet:
- while (!isAnswerAvailable) [answerAvailableCondition wait];
+ // Wait for closeSSHPasswordSheet: to unlock the lock, indicating an answer is available
+ while (![answerAvailableLock tryLock]) usleep(25000);
- // save the answer
+ // Save the answer
NSString *thePassword = nil;
if (requestedPassphrase) {
thePassword = [NSString stringWithString:requestedPassphrase];
[requestedPassphrase release], requestedPassphrase = nil;
}
- //unlock condition
- [answerAvailableCondition unlock];
+ // Unlock the lock again
+ [answerAvailableLock unlock];
- //return the answer
+ // Return the answer
return thePassword;
}
- (void) workerGetPasswordForQuery:(NSString *)theQuery
@@ -577,7 +582,6 @@
*/
- (IBAction) closeSSHPasswordSheet:(id)sender
{
- [answerAvailableCondition lock];
requestedResponse = [sender tag]==1 ? YES : NO;
[NSApp endSheet:sshPasswordDialog];
[sshPasswordDialog orderOut:nil];
@@ -602,9 +606,7 @@
}
}
- isAnswerAvailable = YES;
- [answerAvailableCondition signal];
- [answerAvailableCondition unlock];
+ [[answerAvailableLock onMainThread] unlock];
}
@@ -621,6 +623,9 @@
[tunnelConnection invalidate];
[tunnelConnection release];
[debugMessages release];
+ [answerAvailableLock tryLock];
+ [answerAvailableLock unlock];
+ [answerAvailableLock release];
if (password) [password release];
if (keychainName) [keychainName release];
if (keychainAccount) [keychainAccount release];