aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/MCPKit
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2010-09-20 00:05:43 +0000
committerrowanbeentje <rowan@beent.je>2010-09-20 00:05:43 +0000
commitb41b771c70c7ce6787b651bcc5a63f3f13359474 (patch)
treefa1c57d76ae1b7e7ac6830ac5d58060e689385c2 /Frameworks/MCPKit
parent4c1ea21e96c0b1bf21f483e7d4de9264b04bb1e2 (diff)
downloadsequelpro-b41b771c70c7ce6787b651bcc5a63f3f13359474.tar.gz
sequelpro-b41b771c70c7ce6787b651bcc5a63f3f13359474.tar.bz2
sequelpro-b41b771c70c7ce6787b651bcc5a63f3f13359474.zip
- A further attempt to improve MySQL library crashes by improving threaded pings. This returns to an old approach by attempting to use interrupt signals to force a hung network read to close; however, the signal is now sent by the watchdog thread in a thread-safe fashion to specifically target the locking thread. If this approach works we'll probably consolidate the ping code to use it throughout.
- Update localizable strings
Diffstat (limited to 'Frameworks/MCPKit')
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m34
1 files changed, 33 insertions, 1 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
index 9cb913f0..3dab324d 100644
--- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
@@ -46,6 +46,8 @@ BOOL pingActive;
NSInteger pingFailureCount;
BOOL keepAliveActive;
+static void forceThreadExit(int signalNumber);
+
const NSUInteger kMCPConnectionDefaultOption = CLIENT_COMPRESS | CLIENT_REMEMBER_OPTIONS | CLIENT_MULTI_RESULTS;
const char *kMCPConnectionDefaultSocket = MYSQL_UNIX_ADDR;
const char *kMCPSSLCipherList = "DHE-RSA-AES256-SHA:AES256-SHA:DHE-RSA-AES128-SHA:AES128-SHA:AES256-RMD:AES128-RMD:DES-CBC3-RMD:DHE-RSA-AES256-RMD:DHE-RSA-AES128-RMD:DHE-RSA-DES-CBC3-RMD:RC4-SHA:RC4-MD5:DES-CBC3-SHA:DES-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC-SHA";
@@ -845,6 +847,7 @@ void pingConnectionTask(void *ptr)
uint64_t currentTime_t;
Nanoseconds currentNanoseconds;
double pingStartTime;
+ BOOL threadCancelled = NO;
if (!mConnected || keepAliveThread != NULL) {
// unlock the connection now. it has been locked in keepAlive:
@@ -886,8 +889,13 @@ void pingConnectionTask(void *ptr)
// cancellation of the incorrect thread.
currentTime_t = mach_absolute_time() - connectionStartTime;
currentNanoseconds = AbsoluteToNanoseconds(*(AbsoluteTime *)&(currentTime_t));
- if ((UnsignedWideToUInt64(currentNanoseconds) - pingStartTime) * 1e-9 > pingTimeout && keepAliveActive) {
+ if ((UnsignedWideToUInt64(currentNanoseconds) - pingStartTime) * 1e-9 > pingTimeout && keepAliveActive && !threadCancelled) {
pthread_cancel(keepAliveThread);
+ threadCancelled = YES;
+
+ // If the timeout has been exceeded by an additional two seconds, kill the thread.
+ } else if ((UnsignedWideToUInt64(currentNanoseconds) - pingStartTime) * 1e-9 > (pingTimeout + 2) && keepAliveActive) {
+ pthread_kill(keepAliveThread, SIGUSR1);
keepAliveActive = NO;
}
} while (keepAliveActive);
@@ -905,15 +913,39 @@ void pingConnectionTask(void *ptr)
*/
void performThreadedKeepAlive(void *ptr)
{
+
+ // Set up a signal handler for SIGUSR1, to handle forced timeouts.
+ struct sigaction timeoutAction;
+ timeoutAction.sa_handler = forceThreadExit;
+ sigemptyset(&timeoutAction.sa_mask);
+ timeoutAction.sa_flags = 0;
+ sigaction(SIGUSR1, &timeoutAction, NULL);
+
if (mysql_ping((MYSQL *)ptr)) {
pingFailureCount++;
} else {
pingFailureCount = 0;
}
keepAliveActive = NO;
+
+
+ // Reset and clear the SIGUSR1 used to check connection timeouts.
+ timeoutAction.sa_handler = SIG_IGN;
+ sigemptyset(&timeoutAction.sa_mask);
+ timeoutAction.sa_flags = 0;
+ sigaction(SIGUSR1, &timeoutAction, NULL);
}
/**
+ * Support forcing a thread to exit as a result of a signal.
+ */
+static void forceThreadExit(int signalNumber)
+{
+ pthread_exit(NULL);
+}
+
+
+/**
* Restore the connection encoding details as necessary based on the delegate-provided
* details.
*/