aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2012-05-15 23:40:08 +0000
committerrowanbeentje <rowan@beent.je>2012-05-15 23:40:08 +0000
commitd2237c05664461e086664d25fbe717a06e9b5b75 (patch)
tree09a12ae538f4671f44866008bd493a47168f8b19 /Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m
parent25238e46acd039cdaf410f31b2f064f2ea3db057 (diff)
downloadsequelpro-d2237c05664461e086664d25fbe717a06e9b5b75.tar.gz
sequelpro-d2237c05664461e086664d25fbe717a06e9b5b75.tar.bz2
sequelpro-d2237c05664461e086664d25fbe717a06e9b5b75.zip
Improve connection keepalive, disconnect, and connection loss after reviewing crash logs and testing a number of situations:
- Improve stability of closing connections after a connection loss - Minimise prompting a user for connection state restore if closing windows/tabs - Allow cancellation of keepalive ping threads to prevent crashes after deallocation of parent - Manually handle ping thread state struct memory to avoid cross-thread deallocation issues - Improve disconnection speed and resilience
Diffstat (limited to 'Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m')
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m38
1 files changed, 31 insertions, 7 deletions
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m
index 26276bda..4dbed002 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m
@@ -131,7 +131,8 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
keepAliveInterval = 60;
keepAlivePingFailures = 0;
lastKeepAliveTime = 0;
- keepAlivePingThread = NULL;
+ keepAliveThread = nil;
+ keepAlivePingThread_t = NULL;
keepAlivePingThreadActive = NO;
keepAliveLastPingSuccess = NO;
keepAliveLastPingBlocked = NO;
@@ -206,6 +207,9 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
[keepAliveTimer invalidate];
[keepAliveTimer release];
+ // If a keepalive thread is active, cancel it
+ [self _cancelKeepAlives];
+
// Disconnect if appropriate (which should also disconnect any proxy)
[self disconnect];
@@ -326,8 +330,16 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
- (void)disconnect
{
+ // If state is connection lost, set state directly to disconnected.
+ if (state == SPMySQLConnectionLostInBackground) {
+ state = SPMySQLDisconnected;
+ }
+
// Only continue if a connection is active
- if (state != SPMySQLConnected && state != SPMySQLConnecting) return;
+ if (state != SPMySQLConnected && state != SPMySQLConnecting) {
+ return;
+ }
+
state = SPMySQLDisconnecting;
// If a query is active, cancel it
@@ -335,12 +347,12 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
// Allow any pings or cancelled queries to complete, inside a time limit of ten seconds
uint64_t disconnectStartTime_t = mach_absolute_time();
- do {
+ while (![self _tryLockConnection]) {
usleep(100000);
if (_elapsedSecondsSinceAbsoluteTime(disconnectStartTime_t) > 10) break;
- } while (![self _tryLockConnection]);
+ }
[self _unlockConnection];
- if (keepAlivePingThread != NULL) pthread_cancel(keepAlivePingThread), keepAlivePingThread = NULL;
+ [self _cancelKeepAlives];
// Close the underlying MySQL connection if it still appears to be active, and not reading
// or writing. While this may result in a leak of the MySQL object, it prevents crashes
@@ -499,6 +511,7 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
*/
- (MYSQL *)_makeRawMySQLConnectionWithEncoding:(NSString *)encodingName isMasterConnection:(BOOL)isMaster
{
+ if ([[NSThread currentThread] isCancelled]) return NULL;
// Set up the MySQL connection object
MYSQL *theConnection = mysql_init(NULL);
@@ -625,6 +638,11 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
}
}
+ if ([[NSThread currentThread] isCancelled]) {
+ [reconnectionPool release];
+ return NO;
+ }
+
isReconnecting = YES;
// Store certain details about the connection, so that if the reconnection is successful
@@ -648,6 +666,12 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
// If no network is present, wait for a short time for one to become available
[self _waitForNetworkConnectionWithTimeout:10];
+ if ([[NSThread currentThread] isCancelled]) {
+ isReconnecting = NO;
+ [reconnectionPool release];
+ return NO;
+ }
+
// If there is a proxy, attempt to reconnect it in blocking fashion
if (proxy) {
uint64_t loopIterationStart_t, proxyWaitStart_t;
@@ -719,7 +743,7 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
}
// If the reconnection succeeded, restore the connection state as appropriate
- if (state == SPMySQLConnected) {
+ if (state == SPMySQLConnected && ![[NSThread currentThread] isCancelled]) {
reconnectSucceeded = YES;
if (databaseToRestore) {
[self selectDatabase:databaseToRestore];
@@ -733,7 +757,7 @@ const char *SPMySQLSSLPermissibleCiphers = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RS
// If the connection failed and the connection is permitted to retry,
// then retry the reconnection.
- } else if (canRetry) {
+ } else if (canRetry && ![[NSThread currentThread] isCancelled]) {
// Default to attempting another reconnect
SPMySQLConnectionLostDecision connectionLostDecision = SPMySQLConnectionLostReconnect;