I’ve started getting a consistent hang in one of our unit tests, in which we’re
uploading 30MB of data to an HTTP server via a PUT request. The body is a
stream of data generated at runtime; to stream this to an NSURLTask we call
CFStreamCreateBoundPair, set the resulting input stream as the task’s
HTTPBodyStream, and then schedule the paired output stream with our runloop and
write to it when notified space is available.
This is on OS X 10.11.4 (with both of the latest two betas.) It hasn’t occurred
on another machine running 10.11.3. I’m going to file a Radar, but I’m also
asking here in case anyone else has run into this and/or knows of a workaround.
My code's write call blocks forever like this — it’s been notified the output
stream has space, but while writing the output stream is stuck acquiring a
mutex:
frame #0: 0x00007fff88e8cde6 libsystem_kernel.dylib`__psynch_mutexwait + 10
frame #1: 0x00007fff965b7e4a
libsystem_pthread.dylib`_pthread_mutex_lock_wait + 89
frame #2: 0x00007fff9528e274 CoreFoundation`boundPairWrite + 52
frame #3: 0x00007fff951aafa5 CoreFoundation`CFWriteStreamWrite + 437
* frame #4: 0x0000000107116b5d CouchbaseLite`-[CBLMultiStreamWriter
writeToOutput](self=0x000060c00004f780, _cmd="writeToOutput") + 429 at
CBLMultiStreamWriter.m:254
frame #5: 0x0000000107117712 CouchbaseLite`-[CBLMultiStreamWriter
stream:handleEvent:](self=0x000060c00004f780, _cmd="stream:handleEvent:",
stream=0x000060d000056170, event=NSStreamEventHasSpaceAvailable) + 1506 at
CBLMultiStreamWriter.m:288
frame #6: 0x00007fff95200094 CoreFoundation`_signalEventSync + 180
frame #7: 0x00007fff9521d29e
CoreFoundation`_cfstream_shared_signalEventSync + 478
frame #8: 0x00007fff951de881
CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
At the same time, the CFNetwork thread is also blocked inside boundPairRead,
presumably the mate of the stream we’re writing to:
* thread #7: tid = 0x5393e, 0x00007fff88e8cde6
libsystem_kernel.dylib`__psynch_mutexwait + 10, name =
'com.apple.NSURLConnectionLoader'
* frame #0: 0x00007fff88e8cde6 libsystem_kernel.dylib`__psynch_mutexwait + 10
frame #1: 0x00007fff965b7e4a
libsystem_pthread.dylib`_pthread_mutex_lock_wait + 89
frame #2: 0x00007fff9528dc57 CoreFoundation`boundPairRead + 151
frame #3: 0x00007fff951b49c5 CoreFoundation`CFReadStreamRead + 389
frame #4: 0x00007fff96c22b1e
CFNetwork`RequestBodyStreamProvider::readBodyStream(bool) + 308
frame #5: 0x00007fff95200094 CoreFoundation`_signalEventSync + 180
frame #6: 0x00007fff9521c67b CoreFoundation`_cfstream_solo_signalEventSync
+ 251
frame #7: 0x00007fff951fd8fc CoreFoundation`_CFStreamSignalEvent + 476
frame #8: 0x00007fff9528dec8 CoreFoundation`boundPairRead + 776
frame #9: 0x00007fff951b49c5 CoreFoundation`CFReadStreamRead + 389
frame #10: 0x00007fff96c22b1e
CFNetwork`RequestBodyStreamProvider::readBodyStream(bool) + 308
frame #11: 0x00007fff95200094 CoreFoundation`_signalEventSync + 180
frame #12: 0x00007fff9521d29e
CoreFoundation`_cfstream_shared_signalEventSync + 478
frame #13: 0x00007fff951de881
CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #14: 0x00007fff951bdf37 CoreFoundation`__CFRunLoopDoSources0 + 423
frame #15: 0x00007fff951bd4df CoreFoundation`__CFRunLoopRun + 927
frame #16: 0x00007fff951bced8 CoreFoundation`CFRunLoopRunSpecific + 296
frame #17: 0x00007fff96a71111 CFNetwork`+[NSURLConnection(Loader)
_resourceLoadLoop:] + 412
The latter stack looks very suspicious — it’s got two re-entrant calls to
RequestBodyStreamProvider::readBodyStream stacked on top of each other. Frame
12 is a stream signaling an event, which triggers a read in frame 9, but
somehow the read triggers another event in frame 6, which triggers a nested
read in frame 3.
This kind of re-entrant call usually smells trouble to me, and in this case I
strongly suspect that the outer call has a lock on the stream’s mutex, and so
when the inner call tries to lock it again it deadlocks. This would then cause
my thread to get stuck to the tar-baby as well when it tries to write to the
paired stream.
—Jens _______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/macnetworkprog/archive%40mail-archive.com
This email sent to [email protected]