Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

AudioStreamer crashing in iOS 6 #21

Closed
daegloe opened this Issue · 12 comments

3 participants

@daegloe

We're getting an EXC_CRASH (SIGTRAP) in our iOS app at CFReadStreamSetProperty kCFStreamPropertyHTTPShouldAutoredirect inside [AudioStreamer openReadStream]. We only see this on iOS 6, but it's consistent across all devices running that version of the OS. If we comment out that line, it doesn't crash but every URL we feed to the AudioStreamer immediately stops after AS_WAITING_FOR_QUEUE_TO_START with no error.

Have you tested the class with iOS 6? Are you aware of any issues? We've done some heavy debugging and are preparing to open an inquiry with Apple. Just thought I'd check here first.

The actual crash itself is inside CoreFoundation, __CFTypeCollectionRetain to be exact. Below is part of the symbolicated report. I can provide you with more details privately, if you're interested.

Date/Time:       2012-11-02 21:32:34.656 -0400
OS Version:      iOS 6.0.1 (10A525)
Report Version:  104

Exception Type:  EXC_CRASH (SIGTRAP)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Crashed Thread:  1

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   CoreFoundation                  0x3a9254e0 __CFTypeCollectionRetain + 8
1   CoreFoundation                  0x3a88ed6c _CFArrayReplaceValues + 264
2   CoreFoundation                  0x3a88ec5a CFArrayAppendValue + 106
3   CFNetwork                       0x3353d56a HTTPReadStream::_streamImpl_SetProperty(__CFString const*, void const*) + 462
4   CFNetwork                       0x3353d99e non-virtual thunk to HTTPReadStream::_streamImpl_SetProperty(__CFString const*, void const*) + 6
5   CFNetwork                       0x3357d1da CoreStreamBase::_streamInterface_SetProperty(__CFString const*, void const*) + 18
6   CFNetwork                       0x3357bb4e CoreStreamCFStreamSupport<__CFReadStream*, CoreReadStream>::_stream_setProperty(__CFReadStream*, __CFString const*, void const*, void*) + 6
7   CoreFoundation                  0x3a8f491c CFReadStreamSetProperty + 96
@alexcrichton
Owner

I have not tested this with iOS 6 before, so I'm not aware of anything previously. Are you sending the request to a URL which does indeed make a redirect? If you are it kind of makes sense when you comment out the line that it just hangs waiting for more data.

One thing you may want to try is possibly the CFHTTPReadStreamSetRedirectsAutomatically method. It's deprecated, but it may not cause a crash?

I certainly wouldn't mind trying to help you with this if you're willing to share more details.

@daegloe

Forgive me, I should have been more specific.

The URLs do not have a redirect, so setting kCFStreamPropertyHTTPShouldAutoredirect isn't necessary to play the stream.

When commenting out that code, the app no longer crashes but the audio streams never play. It seems that in iOS 6, calling CFReadStreamSetProperty on the stream exposes some kind of issue with the stream itself, which results in a crash. Without CFReadStreamSetProperty, the stream is simply unable to function correctly and fails, but without a specific error. Both the crash and the stream failure are likely manifestations of the same underlying iOS 6-specific issue.

I spoke with someone at Apple who suggested this might be ARC related. Do you happen to have a non-ARC version of the class that we could try out? Would save us the trouble of de-ARC-ifying the codebase.

@alexcrichton
Owner

Hmm, it sounds like there might be two things going on here.

  1. If you're not causing a redirect, it's not clear to me why not specifying the auto redirect would prevent audio streams from ever playing. You may want to try printing out the incoming data from the stream to make sure you're actually receiving the data you're expecting to receive. Otherwise this may just be a problem which is also stemmed from ARC problems.
  2. Having an ARC problem is definitely bad. I don't have a non-ARC version off-hand. You'd probably have to go back to the original repository which didn't have ARC at all. Regardless though, I'd like to figure out what the current problem is. You could try removing calls to CFRelease throughout the class, but I'm not sure if that will fix it.
@daegloe

We believe the CFReadStreamSetProperty kCFStreamPropertyHTTPShouldAutoredirect crash is a red herring, and that the real culprit is the CFReadStreamRef itself. What the exact issue is, we do not yet know. But we believe the audio stream fails because of this same issue with the CFReadStreamRef. We can see the HTTP server responding to the request and sending data, and we can also see that data being received by the client on the network stack level. The data, however, is not made available through the CFReadStreamRef.

Again, this only happens when running on iOS 6. It could very well be exposing a CFNetwork-related iOS 6 bug. Although that seems hard to believe because the AudioStreamer code is fairly boilerplate so you'd expect to see this issue being discussed elsewhere. But one never knows.

Our Apple contact suggested looking into ARC as a first step, before opening an official inquiry.

@daegloe

Turns out I misspoke. When the redirect code is commented out, the audio stream fails with the error "Failed to open file stream". It immediately jumps from Waiting for Data to Stopped.

@daegloe

OK, so it looks like my engineer was incorrect. The HTTP request from the app is never made. After some additional debugging, it appears that the AudioStreamer instance loses the url value by the time openReadStream is called. We can see it being set correctly, but then it reverts to nil. Again, this only happens when running on iOS 6.

@alexcrichton
Owner

Have you tried breaking on writes to the instance variable?

@daegloe

We've tried setting a watch on the variable, but that doesn't seem to do the trick.

One detail I forgot to mention, this issue only occurs when running on an actual iPhone w/ iOS 6. If we run the app in the iOS 6 Simulator, everything is fine.

To make matters even more bizarre, we just discovered that if we break on streamWithURL and then step through the method before continuing execution, it works!

Any thoughts?

@daegloe

To be specific, if we step through the line stream->url = url; in the streamWithURL method, it works. If we break on that line and simply continue execution, it still fails with the url ivar reverting to nil by the time it calls openReadStream.

@alexcrichton
Owner

Beyond adding an assertion that the url isn't nil when you pass it into CFHTTPMessageCreateRequest, I can't think of much off hand. If this is definitely a problem where the url is nil by the time is gets passed in, then zeroing in on when it's nil-ified is the first thing to look into.

It's possible that gdb tampers with timings and interleavings, so that's why it may not show up in the debugger and only when running naturally.

@daegloe

We solved it. It turns out that when we ran our code through the Xcode ARC refactoring wizard, it changed the url ivar and property declarations to __weak. Switching it back fixed the problem.

@einsteinx2

I just want to leave a huge thanks to daegloe! We ran into a similar issue with our app (not using this repo, just using CFNetwork), and you saved me an incalculable amount of time tracking this down. So thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.