semaphore_wait_trap, GCD and CocoaAsyncSocket - ios

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.

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.

Related

Unordered socket read & close notification using IOCP

Most server framework/examples using sockets and I/O completion ports makes notifications in a way I couldn't completely figure out the purpose.
Upon read packets are processed, usually they are reordered to circumvent thread scheduling issues processing packets out of order no matter IOCP ensure a FIFO queue.
The problem is when a socket is closed gracefully or by an error. I saw in both situation, and again by the o.s. thread scheduler, the close notification may be sent to the application (i.e. http server using the framework) "before" the notification of data previously readed.
I think that the close notification should be queued in such way so the application receives it after previous reads.
Is there any intended use in most code I saw or my behavior may be correct depending on the situation?
What you suggest makes sense and I would imagine that any code that handles graceful close (a read returning 0 bytes) would do so by processing it after any proceeding successful read. Errors coming out of GetQueuedCompletionStatus(), such as connection reset errors, etc, are harder to integrate into the receive flow as they occur out of band as far as the receive data is concerned. Your question's a bit vague and depends very much on the code you're using and how you (or the people who wrote that code) want to handle these things. There is no single correct way, IMHO.

Persistent TCPSocket and Ruby threads

I am connecting to a server as a client using TCPSocket. The main point is to keep connection open and send there or receive from there messages as soon as they arrive.
There are no problems with sending messages, but doing socket.recv(n) in main thread when server has nothing to respond with, makes client's main thread to pause while waiting for data.
What is the good practice to work with persistent connections in Ruby to prevent main thread blocking?
Let's suppose that extra thread should be used. Where to insert this thread initialization in Rails app? Make a worker process?
Receiving data on a dedicated thread is certainly possible. But also consider using IO#select or IO#read_nonblock. (TCPSocket is a subclass of IO.) If you are waiting for data to come from any one of several sockets, IO#select would be ideal. If you are doing some other processing on the main thread, but also need to remain responsive to input coming in from a socket, you can call IO#read_nonblock at intervals.

What is the real necessity of Apple's Reachability framework?

I have read up on the Reachability framework and am still confused why the definition of a host is being reachable is "when a data packet... can leave the local device".
If reachability returns "yes" then it seems that I still need to try and make a socket connection and until that actually connects I do not really know my host is up. Why doesn't Reachability use a Ping to get a better idea of whether the host is actually up? And what is the need of this framework in the first place?
My guess is these two, but if anyone knows any other reasons to use the Reachability framework please let me know.
1) Reachability gives a callback which gives instant notification when the internet comes back up. When this occurs a socket connection can be immediately attempted. However in 99% of applications it seems acceptable to just attempt a socket connection every few seconds, or worst case just try to make the connection when a user does a certain action. Granted, this is not an ideal solution but I don't see why the Reachability framework would ever be really necessary for this reason.
2) Even in the case where a socket connection has been made to the server, Reachability gives an important bit of information about whether the network is G3/WiFi. I think this is the only time Reachability is really necessary because it allows optimization of behavior according to network type.
Reachability is actually quite useful: Given your case (1), you forget that it gives you notifications on both network up and down events. Meaning you can set the callback to handle events such as losing network connectivity (which happens more than you would like on both WiFi and 3G).
Additionally, testing a connection using a socket is not that straightforward; Socket operations are , by default, blocking, and though you can use asynchronous operations (or threads), doing so involves writing code. Not to mention trying DNS when the network is down, and other such issues. By setting a reachability target using the framework, you can alleviate the need to handle all sorts of issues like these yourself, and simply wait for that callback.
Hope this helps,
TG

why my background working thread is blocking UI thread?

I am working on an app, which uploads native contacts to server then get responses(JSON, a contact list that already installed the app). When native contacts are large enough, server response will be slow and unstable. And user cannot do other things. so I put network request into background thread. every time I will upload 100 contacts, do some tasks , then next 100 contacts until loop finish.
But in running, the result is not as expected. background thread is running, it keeps to request server. UI thread is blocked, I still cannot do anything.
is this cause a long loop in background thread? Although I have 2 thread, but they will compete CPU resources(test device is iPod, 1 core. And I think this may not related core numbers)?
Could anyone tell me hints on how to handle this kind of scenario? Thanks in advance!
Update:
I have found the root cause. A global variable in App delegate is set to wrong value, therefore UI behavior is weird. I found this by comment all network request method. So this problem is not related with multiple threading. Sorry for the bother.
I think there needs to be some clarification as to how you are performing the network operations.
1st, NSOperatiomQueue deals with NSOperations, so you are presumably wrapping your network code in an NSOperation subclass.
2nd, are you using NSURLConnections for your networking code?
3rd, is the blocking part the NSURLConnection or you delegate callback for NSURLConnection?
1 thing to note is that plain ol' NSURLConnections are implemented under the hood multithreaded. The object is placed into your main threads run loop by default (when run from the main thread), but the object is just a wrapper that handles callbacks to the delegate from the lower level networking code (BSD sockets) which happens on another thread.
You really shouldn't be able to block your UI with NSURLConnections on the main thread, unless A) you are blocking the thread with expensive code in the delegate callback methods or B) you are overwhelming your run loop with too many simultaneous URL connections (which is where NSOperationQueue's setMaxConcurrentOperationsCount: comes into play)

I/O Completion Port, How to free Per Socket Context and Per I/O Context?

I'm using IOCP on UDP socket, and the UDP socket may be closed in another thread. So, how can I free Per Socket Context and Per I/O Context which associated with SOCKET safely?
When I close the socket, there will still be un-completed I/O request in kernel queue.
If I free context just when socket closed, the GetQueueCompletionStatus may failed.
Now, my question is when to free context?
I use reference counting on all of my per socket and per I/O data structures. It makes this kind of thing easy as they are deleted when their references drop to 0. For some example code which shows one way to do this you could take a look at my free IOCP framework which you can download from here.
Use a mutex to enforce mutual exclusion in a critical section of your code that will check the availability of the socket, and open it if necessary. Lock the socket to that thread, and release it appropriately when finished.
I reuse my per-socket structures. After I have received completion events for all of the read and write operations that are required for that connection, I call TransmitFile with the TF_DISCONNECT and TF_REUSE_SOCKET flags to reset the socket without having to close it. I also reset the per-connection data once the completion event for the TransmitFile call comes through.
Close the socket first. You will get error (I think it is ERROR_OPERATION_ABORTED) from GetQueuedCompletionStatus, and then it is right time to free the structure. There are no other uncompleted requests on this connection in kernel queue by then, completion packets are maintained in FIFO order, and error packet will definitely be the last one for this connection.

Resources