From d9a55ae39cc96b3be95353b1fdc784c96d7be730 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Sun, 31 Oct 2010 13:04:48 -0400 Subject: [PATCH] Add a quit source to the DebuggerConnection's run loop to properly handle closing. --- Source/DebuggerConnection.h | 5 +++- Source/DebuggerConnection.m | 50 ++++++++++++++++++++++++++++++++++--- Source/DebuggerProcessor.m | 8 +++++- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/Source/DebuggerConnection.h b/Source/DebuggerConnection.h index daf7db3..01c2bb1 100644 --- a/Source/DebuggerConnection.h +++ b/Source/DebuggerConnection.h @@ -45,7 +45,10 @@ // The write stream. Weak. CFWriteStreamRef writeStream_; - + + // Run loop source used to quit the thread. + CFRunLoopSourceRef quitSource_; + // An ever-increasing integer that gives each transaction a unique ID for the // debugging engine. NSUInteger transactionID; diff --git a/Source/DebuggerConnection.m b/Source/DebuggerConnection.m index 3f83717..598c3c1 100644 --- a/Source/DebuggerConnection.m +++ b/Source/DebuggerConnection.m @@ -43,6 +43,8 @@ - (void)performSend:(NSString*)command; - (void)sendQueuedWrites; +- (void)performQuitSignal; + - (void)handleResponse:(NSXMLDocument*)response; - (void)handlePacket:(NSString*)packet; @@ -184,6 +186,14 @@ void SocketAcceptCallback(CFSocketRef socket, [connection socketDidAccept]; } +// Other Run Loop Callbacks //////////////////////////////////////////////////// + +void PerformQuitSignal(void* info) +{ + DebuggerConnection* obj = (DebuggerConnection*)info; + [obj performQuitSignal]; +} + //////////////////////////////////////////////////////////////////////////////// @implementation DebuggerConnection @@ -276,11 +286,23 @@ void SocketAcceptCallback(CFSocketRef socket, CFRunLoopAddSource([runLoop_ getCFRunLoop], source, kCFRunLoopCommonModes); CFRelease(source); + // Create a source that is used to quit. + CFRunLoopSourceContext quitContext = { 0 }; + quitContext.version = 0; + quitContext.info = self; + quitContext.perform = PerformQuitSignal; + quitSource_ = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &quitContext); + CFRunLoopAddSource([runLoop_ getCFRunLoop], quitSource_, kCFRunLoopCommonModes); + [runLoop_ run]; thread_ = nil; runLoop_ = nil; + CFRunLoopSourceInvalidate(quitSource_); + CFRelease(quitSource_); + quitSource_ = NULL; + [pool release]; } @@ -301,16 +323,29 @@ void SocketAcceptCallback(CFSocketRef socket, * Closes a socket and releases the ref. */ - (void)close +{ + if (runLoop_ && quitSource_) { + CFRunLoopSourceSignal(quitSource_); + CFRunLoopWakeUp([runLoop_ getCFRunLoop]); + } +} + +/** + * Quits the run loop and stops the thread. + */ +- (void)performQuitSignal { if (runLoop_) { CFRunLoopStop([runLoop_ getCFRunLoop]); } - + // The socket goes down, so do the streams, which clean themselves up. if (socket_) { CFSocketInvalidate(socket_); CFRelease(socket_); + socket_ = NULL; } + self.queuedWrites = nil; connected_ = NO; [writeQueueLock_ release]; @@ -321,8 +356,15 @@ void SocketAcceptCallback(CFSocketRef socket, */ - (void)socketDisconnected { - [self close]; - [delegate_ connectionDidClose:self]; + if (connected_) { + // The state still is connected, which means that we did not get here + // through normal disconnected procedure (a call to |-close|, followed by + // the downing of the socket and the stream, which also produces this + // messsage). Instead, the stream callbacks encountered EOF unexpectedly. + [self close]; + } + if ([delegate_ respondsToSelector:@selector(connectionDidClose:)]) + [delegate_ connectionDidClose:self]; } /** @@ -419,6 +461,8 @@ void SocketAcceptCallback(CFSocketRef socket, */ - (void)errorEncountered:(NSString*)error { + if (![delegate_ respondsToSelector:@selector(errorEncountered:)]) + return; [delegate_ performSelectorOnMainThread:@selector(errorEncountered:) withObject:error waitUntilDone:NO]; diff --git a/Source/DebuggerProcessor.m b/Source/DebuggerProcessor.m index cad456a..c392d32 100644 --- a/Source/DebuggerProcessor.m +++ b/Source/DebuggerProcessor.m @@ -117,7 +117,8 @@ */ - (void)reconnect { - [connection_ close]; + if (connection_.connected) + [connection_ close]; self.status = @"Connecting"; [connection_ connect]; } @@ -222,6 +223,11 @@ // Specific Response Handlers ////////////////////////////////////////////////// #pragma mark Response Handlers +- (void)errorEncountered:(NSString*)error +{ + [delegate errorEncountered:error]; +} + /** * Initial packet received. We've started a brand-new connection to the engine. */ -- 2.22.5