Search code examples
iosmultithreadinggrand-central-dispatchfmdbcocoaasyncsocket

semaphore_wait_trap, GCD and CocoaAsyncSocket


I am currently building an App using CocoaAsyncSocket. I connect to a TCP server and read/write some data.

I create the socket using

self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

When data is received, I use FMDB to save it into a database. Everything works fine, until I send the App to Background (using Homebutton), and then resuming to it. The UI is frozen and not responsive, the Debugger shows, that it is waiting at semaphore_wait_trap.


Solution

  • Don't use the main queue as an argument to the delegateQueue parameter. Use one of the global concurrent queues or a serial/parallel queue you create yourself.

    Update: I just looked at the implementation for GCDAsyncSocket and now realize that the delegate queue and methods are fired async to the actual read/write operations, which happen on an internal queue, so my suggestion was either irrelevant (depending on what you're actually doing in the completion methods) or, at the very least, not pertinent to the problem you're having. I think what's happening is that the internal socket(s) are being closed, as per the iOS App Programming Guide. To wit:

    • Be prepared to handle connection failures in your network-based sockets. The system may tear down socket connections while your app is suspended for any number of reasons. As long as your socket-based code is prepared for other types of network failures, such as a lost signal or network transition, this should not lead to any unusual problems. When your app resumes, if it encounters a failure upon using a socket, simply reestablish the connection.

    The GCDAsyncSocket class you're using has some methods which seem to be aimed at dealing with this, such as -autoDisconnectOnClosedReadStream, and I think you just need to add some code to handle the disconnection / connection re-establishment case.