From c8d0d4adf24505a1d5b45e468980d8bbd0cc7c13 Mon Sep 17 00:00:00 2001 From: Vyacheslav Khorkov Date: Tue, 4 Oct 2016 20:21:51 +0500 Subject: [PATCH] Fixed the crash with async disconnect in StreamSession. --- stream/Apple/StreamSession.h | 8 ++-- stream/Apple/StreamSession.mm | 83 +++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/stream/Apple/StreamSession.h b/stream/Apple/StreamSession.h index edcf4ffb..49ad399b 100644 --- a/stream/Apple/StreamSession.h +++ b/stream/Apple/StreamSession.h @@ -60,12 +60,10 @@ namespace videocore { StreamSessionCallback_T m_callback; StreamStatus_T m_status; - int m_outSocket; - + int m_outSocket; + dispatch_queue_t m_serialQueue; }; } } - - -#endif /* defined(__videocore__StreamSession__) */ +#endif /* defined(__videocore__StreamSession__) */ \ No newline at end of file diff --git a/stream/Apple/StreamSession.mm b/stream/Apple/StreamSession.mm index c1e32a75..381afee5 100644 --- a/stream/Apple/StreamSession.mm +++ b/stream/Apple/StreamSession.mm @@ -62,12 +62,19 @@ - (void) stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { m_streamCallback = [[NSStreamCallback alloc] init]; SCB(m_streamCallback).session = this; + m_serialQueue = dispatch_queue_create("com.videocore.network", DISPATCH_QUEUE_SERIAL); } StreamSession::~StreamSession() { disconnect(); [SCB(m_streamCallback) release]; + if (m_serialQueue) { +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + dispatch_release(m_serialQueue); +#endif + m_serialQueue = nil; + } } void @@ -88,50 +95,55 @@ - (void) stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode &readStream, &writeStream); + CFReadStreamSetProperty(readStream, + kCFStreamPropertyShouldCloseNativeSocket, + kCFBooleanTrue); + CFWriteStreamSetProperty(writeStream, + kCFStreamPropertyShouldCloseNativeSocket, + kCFBooleanTrue); + m_inputStream = (NSInputStream*)readStream; m_outputStream = (NSOutputStream*)writeStream; - - dispatch_queue_t queue = dispatch_queue_create("com.videocore.network", 0); - - if(m_inputStream && m_outputStream) { - dispatch_async(queue, ^{ + if (m_inputStream && m_outputStream) { + dispatch_async(m_serialQueue, ^{ this->startNetwork(); }); } else { nsStreamCallback(nullptr, NSStreamEventErrorOccurred); } - dispatch_release(queue); } - } void StreamSession::disconnect() { - if(m_outputStream) { - //if(m_runLoop) { - // [NSOS(m_outputStream) removeFromRunLoop:NSRL(m_runLoop) forMode:NSDefaultRunLoopMode]; - //} - [NSOS(m_outputStream) close]; - [NSOS(m_outputStream) release]; - m_outputStream = nullptr; - } - if(m_inputStream) { - //if(m_runLoop) { - // [NSOS(m_inputStream) removeFromRunLoop:NSRL(m_runLoop) forMode:NSDefaultRunLoopMode]; - //} - [NSIS(m_inputStream) close]; - [NSIS(m_inputStream) release]; - m_inputStream = nullptr; - } - - if(m_runLoop) { - CFRunLoopStop([NSRL(m_runLoop) getCFRunLoop]); - [(id)m_runLoop release]; - m_runLoop = nullptr; - } + dispatch_sync(m_serialQueue, ^{ + if (m_outputStream) { + if (m_runLoop) { + [NSOS(m_outputStream) removeFromRunLoop:NSRL(m_runLoop) forMode:NSDefaultRunLoopMode]; + } + [NSOS(m_outputStream) close]; + [NSOS(m_outputStream) release]; + m_outputStream = nullptr; + } + + if (m_inputStream) { + if (m_runLoop) { + [NSOS(m_inputStream) removeFromRunLoop:NSRL(m_runLoop) forMode:NSDefaultRunLoopMode]; + } + [NSIS(m_inputStream) close]; + [NSIS(m_inputStream) release]; + m_inputStream = nullptr; + } + + if (m_runLoop) { + CFRunLoopStop([NSRL(m_runLoop) getCFRunLoop]); + [(id)m_runLoop release]; + m_runLoop = nullptr; + } + }); } ssize_t @@ -180,6 +192,7 @@ - (void) stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode } m_callback(*this, status); } + void StreamSession::nsStreamCallback(void* stream, unsigned event) { @@ -218,6 +231,8 @@ - (void) stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode StreamSession::startNetwork() { m_runLoop = [NSRunLoop currentRunLoop]; + [(NSRunLoop *)m_runLoop retain]; + [NSIS(m_inputStream) setDelegate:SCB(m_streamCallback)]; [NSIS(m_inputStream) scheduleInRunLoop:NSRL(m_runLoop) forMode:NSDefaultRunLoopMode]; [NSOS(m_outputStream) setDelegate:SCB(m_streamCallback)]; @@ -225,9 +240,13 @@ - (void) stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode [NSOS(m_outputStream) open]; [NSIS(m_inputStream) open]; - [(id)m_runLoop retain]; - [NSRL(m_runLoop) run]; + dispatch_queue_t queue = dispatch_queue_create("com.videocore.network.sockets", DISPATCH_QUEUE_SERIAL); + dispatch_async(queue, ^{ + [NSRL(m_runLoop) run]; + }); +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + dispatch_release(queue); +#endif } - } }