2

I'm doing async socket programming, and my code works, most of the time, but sometimes it doesn't. The gist is: I create a socket pair, create read and write streams, and then when I want to write something, I schedule it on a run loop of a separate thread. Like so:

CFStreamClientContext context = {0, sc, NULL, NULL, NULL};
if (CFWriteStreamSetClient(sc.writeStream, kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, myWriteStreamCallBack, &context)) {
 CFWriteStreamScheduleWithRunLoop(sc.writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
}

... where myWriteStreamCallback is a static function of the correct form...

the sockets/streams were opened like so:

CFReadStreamRef readStream  = NULL;
CFWriteStreamRef writeStream = NULL; 

@try {
   // create a pair of streams to the host and open them

  CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, scomm.host, SERVER_PORT, &readStream, &writeStream);
  if (readStream == NULL)     @throw [[[CommunicationReadStreamNotCreatedException alloc] init] autorelease];
  if (writeStream == NULL)    @throw [[[CommunicationWriteStreamNotCreatedException alloc] init] autorelease];
  if (!CFReadStreamOpen(readStream))  @throw [[[CommunicationReadStreamNotOpenedException alloc] init] autorelease];
  if (!CFWriteStreamOpen(writeStream)) @throw [[[CommunicationWriteStreamNotOpenedException alloc] init] autorelease];
  ...

Now to the problem: this code (and there's more, if it'll help anyone), is mostly correct, because it mostly works. However, sometimes, at the very beginning of the program, I can try to send some data this way, and the callback for the socket will correctly be placed on the run loop, but then it'll never get called. Later in the program, the same code will be run with another socket, and the callback will get called (sockets go to the same address).

I know this is vague, but before I get into posting all of the code, does anyone have any rough ideas about things that could potentially cause this? Callbacks sometimes not getting called on runloops, that is.

Oh yeah, I should add that this is obviously some type of race condition - I can unreliably make the problem go away by adding in logging statements at the right places. And then, it sometimes works and sometimes doesn't, with the exact same code. Fun fun.

Colin
  • 3,670
  • 1
  • 25
  • 36

1 Answers1

1

I obtained a solution from "quinn the eskimo" on the apple forums:

The problem was resolution of the host done in one thread and the CFHostRef used in other threads. This is bad.

CFHost creation done in the same thread (the scomm.host object, above) fixes problem.

Kev
  • 118,037
  • 53
  • 300
  • 385
Colin
  • 3,670
  • 1
  • 25
  • 36