Skip to content

Commit e764964

Browse files
committed
Fix for nasty race condition in accepting sockets.
1 parent 2a70052 commit e764964

File tree

5 files changed

+34
-4
lines changed

5 files changed

+34
-4
lines changed

demos/KitchenSink/Resources/examples/socket_connect.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function pumpCallback(e) {
66
if (e.bytesProcessed == -1) { // EOF
77
statusArea.value = "<EOF> - Can't perform any more operations on connected socket";
88
}
9-
if (e.errorDescription == null || e.errorDescription == "") {
9+
else if (e.errorDescription == null || e.errorDescription == "") {
1010
statusArea.value = "DATA: "+e.buffer.toString();
1111
}
1212
else {

iphone/Classes/AsyncSocket.h

+5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ typedef enum AsyncSocketError AsyncSocketError;
6767
**/
6868
- (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket;
6969

70+
/**
71+
* Called when the socket has been attached to run loop, etc. and is ready to hit the big time.
72+
*/
73+
-(void)onSocketReadyInRunLoop:(AsyncSocket *)sock;
74+
7075
/**
7176
* Called when a socket is about to connect. This method should return YES to continue, or NO to abort.
7277
* If aborted, will result in AsyncSocketCanceledError.

iphone/Classes/AsyncSocket.m

+4
Original file line numberDiff line numberDiff line change
@@ -1821,6 +1821,10 @@ - (AsyncSocket*)doAcceptFromSocket:(CFSocketRef)parentSocket withNewNativeSocket
18211821
if(![newSocket attachStreamsToRunLoop:runLoop error:nil]) goto Failed;
18221822
if(![newSocket configureStreamsAndReturnError:nil]) goto Failed;
18231823
if(![newSocket openStreamsAndReturnError:nil]) goto Failed;
1824+
1825+
if ([theDelegate respondsToSelector:@selector(onSocketReadyInRunLoop:)]) {
1826+
[theDelegate onSocketReadyInRunLoop:newSocket];
1827+
}
18241828

18251829
return newSocket;
18261830

iphone/Classes/TiNetworkSocketTCPProxy.h

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ typedef enum {
4141
NSRunLoop* acceptRunLoop;
4242
NSCondition* acceptCondition;
4343
BOOL accepting;
44+
BOOL acceptedReady;
4445

4546
// Information used to hash callbacks and asynch ops to tags.
4647
int asynchTagCount;

iphone/Classes/TiNetworkSocketTCPProxy.m

+23-3
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,16 @@ -(void)startAcceptedSocket:(NSDictionary*)info
233233
NSDictionary* event = [NSDictionary dictionaryWithObjectsAndKeys:self,@"socket",proxy,@"inbound",nil];
234234
[self _fireEventToListener:@"accepted" withObject:event listener:accepted thisObject:self];
235235
}
236-
236+
237+
tempConditionRef = [acceptCondition retain];
238+
[tempConditionRef lock];
239+
if (!acceptedReady) {
240+
[tempConditionRef wait];
241+
}
242+
acceptedReady = NO;
243+
[tempConditionRef unlock];
244+
[tempConditionRef release];
245+
237246
[proxy socketRunLoop];
238247
[proxy forgetSelf];
239248

@@ -572,14 +581,25 @@ -(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt
572581
if (sock != socket) {
573582
return;
574583
}
575-
584+
576585
internalState = SOCKET_CONNECTED;
577586

578587
if (connected != nil) {
579588
NSDictionary* event = [NSDictionary dictionaryWithObjectsAndKeys:self,@"socket",nil];
580589
[self _fireEventToListener:@"connected" withObject:event listener:connected thisObject:self];
581590
}
582-
}
591+
}
592+
593+
// Prevent that goofy race conditon where a socket isn't attached to a run loop before beginning the accepted socket run loop.
594+
-(void)onSocketReadyInRunLoop:(AsyncSocket *)sock
595+
{
596+
NSCondition* tempConditionRef = [acceptCondition retain];
597+
[tempConditionRef lock];
598+
acceptedReady = YES;
599+
[tempConditionRef signal];
600+
[tempConditionRef unlock];
601+
[tempConditionRef release];
602+
}
583603

584604
-(void)onSocketDidDisconnect:(AsyncSocket *)sock
585605
{

0 commit comments

Comments
 (0)