FileSystemTaskParentBase::~FileSystemTaskParentBase() { // This task can be released on different threads because we dispatch it (as // runnable) to main-thread, I/O and then back to the PBackground thread. NS_ProxyRelease(mBackgroundEventTarget, mFileSystem.forget()); NS_ProxyRelease(mBackgroundEventTarget, mRequestParent.forget()); }
AsyncConnectionHelper::~AsyncConnectionHelper() { if (!NS_IsMainThread()) { IDBDatabase* database; mDatabase.forget(&database); IDBTransaction* transaction; mTransaction.forget(&transaction); nsCOMPtr<nsIThread> mainThread; NS_GetMainThread(getter_AddRefs(mainThread)); NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); if (mainThread) { if (database) { NS_ProxyRelease(mainThread, static_cast<nsIIDBDatabase*>(database)); } if (transaction) { NS_ProxyRelease(mainThread, static_cast<nsIIDBTransaction*>(transaction)); } } } NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!"); }
JavaXPCOMInstance::~JavaXPCOMInstance() { nsresult rv = NS_OK; // Need to release these objects on the main thread. nsCOMPtr<nsIThread> thread = do_GetMainThread(); if (thread) { rv = NS_ProxyRelease(thread, mInstance); rv |= NS_ProxyRelease(thread, mIInfo); } NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease"); }
nsInterfaceRequestorAgg::~nsInterfaceRequestorAgg() { nsIInterfaceRequestor* iir = nullptr; mFirst.swap(iir); if (iir) { NS_ProxyRelease(mConsumerTarget, iir); } iir = nullptr; mSecond.swap(iir); if (iir) { NS_ProxyRelease(mConsumerTarget, iir); } }
NS_IMETHODIMP nsStreamListenerTee::OnStopRequest(nsIRequest *request, nsISupports *context, nsresult status) { NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED); // it is critical that we close out the input stream tee if (mInputTee) { mInputTee->SetSink(nullptr); mInputTee = 0; } // release sink on the same thread where the data was written (bug 716293) if (mEventTarget) { nsIOutputStream *sink = nullptr; mSink.swap(sink); NS_ProxyRelease(mEventTarget, sink); } else { mSink = 0; } nsresult rv = mListener->OnStopRequest(request, context, status); if (mObserver) mObserver->OnStopRequest(request, context, status); mObserver = 0; return rv; }
void nsServerSocket::OnSocketDetached(PRFileDesc *fd) { // force a failure condition if none set; maybe the STS is shutting down :-/ if (NS_SUCCEEDED(mCondition)) mCondition = NS_ERROR_ABORT; if (mFD) { NS_ASSERTION(mFD == fd, "wrong file descriptor"); PR_Close(mFD); mFD = nullptr; } if (mListener) { mListener->OnStopListening(this, mCondition); // need to atomically clear mListener. see our Close() method. RefPtr<nsIServerSocketListener> listener = nullptr; { MutexAutoLock lock(mLock); listener = mListener.forget(); } // XXX we need to proxy the release to the listener's target thread to work // around bug 337492. if (listener) { NS_ProxyRelease(mListenerTarget, listener.forget()); } } }
void PeerConnectionMedia::RemoveTransportFlow(int aIndex, bool aRtcp) { int index_inner = GetTransportFlowIndex(aIndex, aRtcp); NS_ProxyRelease( "PeerConnectionMedia::mTransportFlows", GetSTSThread(), mTransportFlows[index_inner].forget()); }
void PeerConnectionMedia::RemoveTransportFlow(int aIndex, bool aRtcp) { int index_inner = GetTransportFlowIndex(aIndex, aRtcp); TransportFlow* flow = mTransportFlows[index_inner].forget().take(); if (flow) { NS_ProxyRelease(GetSTSThread(), flow); } }
NullHttpTransaction::~NullHttpTransaction() { if (mCallbacks) { nsIInterfaceRequestor *cbs = nsnull; mCallbacks.swap(cbs); NS_ProxyRelease(mEventTarget, cbs); } delete mRequestHead; }
JavaXPCOMInstance::~JavaXPCOMInstance() { nsresult rv = NS_OK; #ifdef VBOX nsCOMPtr<nsIEventQueue> eq = do_GetMainThreadQueue(); rv = NS_ProxyRelease(eq.get(), mInstance); rv |= NS_ProxyRelease(eq.get(), mIInfo); #else // Need to release these objects on the main thread. nsCOMPtr<nsIThread> thread = do_GetMainThread(); if (thread) { rv = NS_ProxyRelease(thread, mInstance); rv |= NS_ProxyRelease(thread, mIInfo); } #endif NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease"); }
~nsUrlClassifierCallbackWrapper() { nsCOMPtr<nsIEventQueue> mainEventQ; NS_GetMainEventQ(getter_AddRefs(mainEventQ)); if (mainEventQ) { NS_ProxyRelease(mainEventQ, mInner); } else { NS_WARNING("unable to get main event queue"); } }
SpeechStreamListener::~SpeechStreamListener() { nsCOMPtr<nsIThread> mainThread; NS_GetMainThread(getter_AddRefs(mainThread)); SpeechRecognition* forgottenRecognition = nullptr; mRecognition.swap(forgottenRecognition); NS_ProxyRelease(mainThread, static_cast<DOMEventTargetHelper*>(forgottenRecognition)); }
~nsWyciwygAsyncEvent() { nsCOMPtr<nsIThread> thread = do_GetMainThread(); NS_WARN_IF_FALSE(thread, "Couldn't get the main thread!"); if (thread) { nsIWyciwygChannel *chan = static_cast<nsIWyciwygChannel *>(mChannel); mozilla::unused << mChannel.forget(); NS_ProxyRelease(thread, chan); } }
DocGroup::~DocGroup() { MOZ_ASSERT(mDocuments.IsEmpty()); if (!NS_IsMainThread()) { nsIEventTarget* target = EventTargetFor(TaskCategory::Other); NS_ProxyRelease(target, mReactionsStack.forget()); } mTabGroup->mDocGroups.RemoveEntry(mKey); }
void nsFileCopyEvent::DoCopy() { // We'll copy in chunks this large by default. This size affects how // frequently we'll check for interrupts. const int32_t chunk = nsIOService::gDefaultSegmentSize * nsIOService::gDefaultSegmentCount; nsresult rv = NS_OK; int64_t len = mLen, progress = 0; while (len) { // If we've been interrupted, then stop copying. rv = mInterruptStatus; if (NS_FAILED(rv)) break; int32_t num = std::min((int32_t) len, chunk); uint32_t result; rv = mSource->ReadSegments(NS_CopySegmentToStream, mDest, num, &result); if (NS_FAILED(rv)) break; if (result != (uint32_t) num) { rv = NS_ERROR_FILE_DISK_FULL; // stopped prematurely (out of disk space) break; } // Dispatch progress notification if (mSink) { progress += num; mSink->OnTransportStatus(nullptr, NS_NET_STATUS_WRITING, progress, mLen); } len -= num; } if (NS_FAILED(rv)) mStatus = rv; // Close the output stream before notifying our callback so that others may // freely "play" with the file. mDest->Close(); // Notify completion if (mCallback) { mCallbackTarget->Dispatch(mCallback, NS_DISPATCH_NORMAL); // Release the callback on the target thread to avoid destroying stuff on // the wrong thread. nsIRunnable *doomed = nullptr; mCallback.swap(doomed); NS_ProxyRelease(mCallbackTarget, doomed); } }
NS_IMETHOD Run() { if (mStatement->mAsyncStatement) { sqlite3_finalize(mStatement->mAsyncStatement); mStatement->mAsyncStatement = nullptr; } nsCOMPtr<nsIThread> targetThread(mConnection->threadOpenedOn); NS_ProxyRelease(targetThread, mStatement.forget()); return NS_OK; }
nsWyciwygChannel::~nsWyciwygChannel() { if (mLoadInfo) { nsCOMPtr<nsIThread> mainThread; NS_GetMainThread(getter_AddRefs(mainThread)); nsILoadInfo *forgetableLoadInfo; mLoadInfo.forget(&forgetableLoadInfo); NS_ProxyRelease(mainThread, forgetableLoadInfo, false); } }
nsRequestObserverProxy::~nsRequestObserverProxy() { if (mObserver) { // order is crucial here... we must be careful to clear mObserver // before posting the proxy release event. otherwise, we'd risk // releasing the object on this thread. nsIRequestObserver *obs = nsnull; mObserver.swap(obs); NS_ProxyRelease(mTarget, obs); } }
ManagerId::~ManagerId() { // If we're already on the main thread, then default destruction is fine if (NS_IsMainThread()) { return; } // Otherwise we need to proxy to main thread to do the release // The PBackground worker thread shouldn't be running after the main thread // is stopped. So main thread is guaranteed to exist here. nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); MOZ_ASSERT(mainThread); NS_ProxyRelease(mainThread, mPrincipal.forget().take()); }
nsHTTPListener::~nsHTTPListener() { if (mResponsibleForDoneSignal) send_done_signal(); if (mCondition) PR_DestroyCondVar(mCondition); if (mLock) PR_DestroyLock(mLock); if (mLoader) { nsCOMPtr<nsIThread> mainThread(do_GetMainThread()); NS_ProxyRelease(mainThread, mLoader); } }
nsrefcnt nsXPCWrappedJS::Release(void) { NS_PRECONDITION(0 != mRefCnt, "dup release"); if (mMainThreadOnly && !NS_IsMainThread()) { // We'd like to abort here, but this can happen if someone uses a proxy // for the nsXPCWrappedJS. nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); // If we can't get the main thread anymore we just leak, but this really // shouldn't happen. NS_ASSERTION(mainThread, "Can't get main thread, leaking nsXPCWrappedJS!"); if (mainThread) { NS_ProxyRelease(mainThread, static_cast<nsIXPConnectWrappedJS*>(this)); } return mRefCnt; } // need to take the map lock here to prevent GetNewOrUsed from trying // to reuse a wrapper on one thread while it's being destroyed on another XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); XPCAutoLock lock(rt->GetMapLock()); do_decrement: nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt); NS_LOG_RELEASE(this, cnt, "nsXPCWrappedJS"); if (0 == cnt) { delete this; // also unlinks us from chain return 0; } if (1 == cnt) { if (IsValid()) RemoveFromRootSet(rt->GetMapLock()); // If we are not the root wrapper or if we are not being used from a // weak reference, then this extra ref is not needed and we can let // ourself be deleted. // Note: HasWeakReferences() could only return true for the root. if (!HasWeakReferences()) goto do_decrement; } return cnt; }
HelperBase::~HelperBase() { if (!NS_IsMainThread()) { IDBRequest* request; mRequest.forget(&request); if (request) { nsCOMPtr<nsIThread> mainThread; NS_GetMainThread(getter_AddRefs(mainThread)); NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); if (mainThread) { NS_ProxyRelease(mainThread, static_cast<nsIDOMEventTarget*>(request)); } } } }
/** * Free all used memory and close stream. */ NS_IMETHODIMP nsGIOInputStream::Close() { if (mStream) { g_object_unref(mStream); mStream = nullptr; } if (mHandle) { g_object_unref(mHandle); mHandle = nullptr; } if (mDirList) { // Destroy the list of GIOFileInfo objects... g_list_foreach(mDirList, (GFunc) g_object_unref, nullptr); g_list_free(mDirList); mDirList = nullptr; mDirListPtr = nullptr; } if (mChannel) { nsresult rv = NS_OK; nsCOMPtr<nsIThread> thread = do_GetMainThread(); if (thread) rv = NS_ProxyRelease(thread, mChannel); NS_ASSERTION(thread && NS_SUCCEEDED(rv), "leaking channel reference"); mChannel = nullptr; (void) rv; } mSpec.Truncate(); // free memory // Prevent future reads from re-opening the handle. if (NS_SUCCEEDED(mStatus)) mStatus = NS_BASE_STREAM_CLOSED; return NS_OK; }
NS_IMETHOD Run() { mDict->SyncLoad(); // Release the dictionary on the main thread mozPersonalDictionary *dict; mDict.forget(&dict); nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); if (mainThread) { NS_ProxyRelease(mainThread, static_cast<mozIPersonalDictionary *>(dict)); } else { // It's better to leak the dictionary than to release it on a wrong thread NS_WARNING("Cannot get main thread, leaking mozPersonalDictionary."); } return NS_OK; }
void Service::unregisterConnection(Connection *aConnection) { // If this is the last Connection it might be the only thing keeping Service // alive. So ensure that Service is destroyed only after the Connection is // cleanly unregistered and destroyed. RefPtr<Service> kungFuDeathGrip(this); RefPtr<Connection> forgettingRef; { mRegistrationMutex.AssertNotCurrentThreadOwns(); MutexAutoLock mutex(mRegistrationMutex); for (uint32_t i = 0 ; i < mConnections.Length(); ++i) { if (mConnections[i] == aConnection) { // Because dropping the final reference can potentially result in // spinning a nested event loop if the connection was not properly // shutdown, we want to do that outside this loop so that we can finish // mutating the array and drop our mutex. forgettingRef = mConnections[i].forget(); mConnections.RemoveElementAt(i); break; } } } MOZ_ASSERT(forgettingRef, "Attempt to unregister unknown storage connection!"); // Ensure the connection is released on its opening thread. We explicitly use // aAlwaysDispatch=false because at the time of writing this, LocalStorage's // StorageDBThread uses a hand-rolled PRThread implementation that cannot // handle us dispatching events at it during shutdown. However, it is // arguably also desirable for callers to not be aware of our connection // tracking mechanism. And by synchronously dropping the reference (when // on the correct thread), this avoids surprises for the caller and weird // shutdown edge cases. nsCOMPtr<nsIThread> thread = forgettingRef->threadOpenedOn; NS_ProxyRelease( "storage::Service::mConnections", thread, forgettingRef.forget(), false); }
nsInterfaceRequestorAgg::~nsInterfaceRequestorAgg() { NS_ProxyRelease(mConsumerTarget, mFirst.forget()); NS_ProxyRelease(mConsumerTarget, mSecond.forget()); }
NS_IMETHOD Run() override { nsresult res; MOZ_ASSERT(!NS_IsMainThread()); { mozilla::MonitorAutoLock mon(mDict->mMonitorSave); nsCOMPtr<nsIOutputStream> outStream; NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStream), mFile, PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE, 0664); // Get a buffered output stream 4096 bytes big, to optimize writes. nsCOMPtr<nsIOutputStream> bufferedOutputStream; res = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream), outStream, 4096); if (NS_FAILED(res)) { return res; } uint32_t bytesWritten; nsAutoCString utf8Key; for (uint32_t i = 0; i < mDictWords.Length(); ++i) { CopyUTF16toUTF8(mDictWords[i], utf8Key); bufferedOutputStream->Write(utf8Key.get(), utf8Key.Length(), &bytesWritten); bufferedOutputStream->Write("\n", 1, &bytesWritten); } nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(bufferedOutputStream); NS_ASSERTION(safeStream, "expected a safe output stream!"); if (safeStream) { res = safeStream->Finish(); if (NS_FAILED(res)) { NS_WARNING("failed to save personal dictionary file! possible data loss"); } } // Save is done, reset the state variable and notify those who are waiting. mDict->mSavePending = false; mon.Notify(); // Leaving the block where 'mon' was declared will call the destructor // and unlock. } // Release the dictionary on the main thread. mozPersonalDictionary *dict; mDict.forget(&dict); nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); if (mainThread) { NS_ProxyRelease(mainThread, static_cast<mozIPersonalDictionary *>(dict)); } else { // It's better to leak the dictionary than to release it on a wrong thread. NS_WARNING("Cannot get main thread, leaking mozPersonalDictionary."); } return NS_OK; }
ServiceWorkerCloneData::~ServiceWorkerCloneData() { RefPtr<ipc::SharedJSAllocatedData> sharedData = TakeSharedData(); if (sharedData) { NS_ProxyRelease(__func__, mEventTarget, sharedData.forget()); } }