diff --git a/netwerk/cache2/CacheIOThread.cpp b/netwerk/cache2/CacheIOThread.cpp index c686c0f8d0..fe0a4ddb05 100644 --- a/netwerk/cache2/CacheIOThread.cpp +++ b/netwerk/cache2/CacheIOThread.cpp @@ -215,12 +215,22 @@ nsresult CacheIOThread::Init() mBlockingIOWatcher = MakeUnique(); } + // Increase the reference count while spawning a new thread. + // If PR_CreateThread succeeds, we will forget this reference and the thread + // will be responsible to release it when it completes. + RefPtr self = this; + mThread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 128 * 1024); if (!mThread) { return NS_ERROR_FAILURE; } + + // IMPORTANT: The thread now owns this reference, so it's important that we + // leak it here, otherwise we'll end up with a bad refcount. + // See the dont_AddRef in ThreadFunc(). + Unused << self.forget().take(); return NS_OK; } @@ -382,7 +392,9 @@ void CacheIOThread::ThreadFunc(void* aClosure) { PR_SetCurrentThreadName("Cache2 I/O"); mozilla::IOInterposer::RegisterCurrentThread(); - CacheIOThread* thread = static_cast(aClosure); + // We hold on to this reference for the duration of the thread. + RefPtr thread = + dont_AddRef(static_cast(aClosure)); thread->ThreadFunc(); mozilla::IOInterposer::UnregisterCurrentThread(); }