The immediate crash problem in SIGPIPE is resolved. I do not quite giggle about this solution, but at least the application does not crash. It is not clear that it works 100% correctly, but it seems to behave a little better.
I solved this problem by learning what happens next. While doing some research, I found that perhaps I should use the NSFileHandle writeabilityHandler property to set the block for writing. I do not completely sell this approach (it seemed confusing to me), but it can help.
Solution for processing Writability-handler:
During a web search on writeabilityHandler I stumbled upon a Bert Leung blog entry on some issues he had in a similar area. I took his code and changed it as follows, replacing the @try/@catch/@finally above with this code:
self.pendingData = [NSMutableData dataWithData:(__bridge NSData *)(headerData)]; CFRelease(headerData); CFRelease(response); self.fileHandle.writeabilityHandler = ^(NSFileHandle* thisFileHandle) { int amountSent = send([thisFileHandle fileDescriptor], [self.pendingData bytes], [self.pendingData length], MSG_DONTWAIT); if (amountSent < 0) {
This worked fine, but it did not solve the problem. I was still getting SIGPIPE / EPIPE.
SIGPIPE will disappear!
This was not a surprise since it is almost the same as the previous writeData: but uses send() instead. The main difference is that using send() allows you to set errno . It was very useful, in fact - I got a couple of error codes (in errno), such as 54 (Connection reset by peer) and 32 (Broken pipe). 54 were beautiful, but 32 led to SIGPIPE / EPIPE. Then it dawned on me - maybe I should just ignore SIGPIPE.
Given this thought, I added a couple of hooks to my UIApplicationDelegate in application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
and applicationWillTerminate: ::
- (void)applicationWillTerminate:(UIApplication *)application {
Now, at least the application is not crashing. It is not clear that it works 100% correctly, but it seems that it behaves.
I also switched to the @try/@catch/@finally structure because it is more direct. In addition, after ignoring SIGPIPE, the @catch block starts. Right now I am registering an exception, but only so that I can see that it is working. In the released code, this log will be disabled.