NS_IMETHODIMP nsNotifyAddrListener::Run() { PR_SetCurrentThreadName("Link Monitor"); HANDLE ev = CreateEvent(nullptr, FALSE, FALSE, nullptr); NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY); HANDLE handles[2] = { ev, mShutdownEvent }; OVERLAPPED overlapped = { 0 }; bool shuttingDown = false; overlapped.hEvent = ev; while (!shuttingDown) { HANDLE h; DWORD ret = NotifyAddrChange(&h, &overlapped); if (ret == ERROR_IO_PENDING) { ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE); if (ret == WAIT_OBJECT_0) { CheckLinkStatus(); } else { shuttingDown = true; } } else { shuttingDown = true; } } CloseHandle(ev); return NS_OK; }
void MetroApp::Run() { LogThread(); // Name this thread for debugging and register it with the profiler // as the main gecko thread. char aLocal; PR_SetCurrentThreadName(gGeckoThreadName); profiler_register_thread(gGeckoThreadName, &aLocal); HRESULT hr; hr = sCoreApp->add_Suspending(Callback<__FIEventHandler_1_Windows__CApplicationModel__CSuspendingEventArgs_t>( this, &MetroApp::OnSuspending).Get(), &mSuspendEvent); AssertHRESULT(hr); hr = sCoreApp->add_Resuming(Callback<__FIEventHandler_1_IInspectable_t>( this, &MetroApp::OnResuming).Get(), &mResumeEvent); AssertHRESULT(hr); Log("XPCOM startup initialization began"); nsresult rv = XRE_metroStartup(true); Log("XPCOM startup initialization complete"); if (NS_FAILED(rv)) { Log("XPCOM startup initialization failed, bailing. rv=%X", rv); CoreExit(); } }
// Asynchronously load the database in this thread. static void databaseLoaderEntry(void* threadData) { PR_SetCurrentThreadName("HRTFDatabaseLdr"); HRTFDatabaseLoader* loader = reinterpret_cast<HRTFDatabaseLoader*>(threadData); MOZ_ASSERT(loader); loader->load(); }
void DOMStorageDBThread::ThreadFunc(void* aArg) { PR_SetCurrentThreadName("localStorage DB"); DOMStorageDBThread* thread = static_cast<DOMStorageDBThread*>(aArg); thread->ThreadFunc(); }
// static void CacheIOThread::ThreadFunc(void* aClosure) { PR_SetCurrentThreadName("Cache2 I/O"); mozilla::IOInterposer::RegisterCurrentThread(); CacheIOThread* thread = static_cast<CacheIOThread*>(aClosure); thread->ThreadFunc(); mozilla::IOInterposer::UnregisterCurrentThread(); }
void DOMStorageDBThread::ThreadFunc(void* aArg) { PR_SetCurrentThreadName("localStorage DB"); mozilla::IOInterposer::RegisterCurrentThread(); DOMStorageDBThread* thread = static_cast<DOMStorageDBThread*>(aArg); thread->ThreadFunc(); mozilla::IOInterposer::UnregisterCurrentThread(); }
// Background hang monitor thread function static void MonitorThread(void* aData) { PR_SetCurrentThreadName("BgHangManager"); /* We do not hold a reference to BackgroundHangManager here because the monitor thread only exists as long as the BackgroundHangManager instance exists. We stop the monitor thread in the BackgroundHangManager destructor, and we can only get to the destructor if we don't hold a reference here. */ static_cast<BackgroundHangManager*>(aData)->RunMonitorThread(); }
void StorageDBThread::ThreadFunc(void* aArg) { AutoProfilerRegister registerThread("localStorage DB"); PR_SetCurrentThreadName("localStorage DB"); mozilla::IOInterposer::RegisterCurrentThread(); StorageDBThread* thread = static_cast<StorageDBThread*>(aArg); thread->ThreadFunc(); mozilla::IOInterposer::UnregisterCurrentThread(); }
void LazyIdleThread::InitThread() { PR_SetCurrentThreadName(mName.BeginReading()); // Happens on mThread but mThread may not be set yet... nsCOMPtr<nsIThreadInternal> thread(do_QueryInterface(NS_GetCurrentThread())); MOZ_ASSERT(thread, "This should always succeed!"); if (NS_FAILED(thread->SetObserver(this))) { NS_WARNING("Failed to set thread observer!"); } }
void StartupCache::ThreadedWrite(void *aClosure) { PR_SetCurrentThreadName("StartupCache"); /* * It is safe to use the pointer passed in aClosure to reference the * StartupCache object because the thread's lifetime is tightly coupled to * the lifetime of the StartupCache object; this thread is joined in the * StartupCache destructor, guaranteeing that this function runs if and only * if the StartupCache object is valid. */ StartupCache* startupCacheObj = static_cast<StartupCache*>(aClosure); startupCacheObj->WriteToDisk(); }
void GraphRunner::Run() { PR_SetCurrentThreadName("GraphRunner"); MonitorAutoLock lock(mMonitor); while (true) { while (mThreadState == ThreadState::Wait) { mMonitor.Wait(); // Wait for mStateEnd to update or for shutdown } if (mThreadState == ThreadState::Shutdown) { break; } TRACE(); mStillProcessing = mGraph->OneIterationImpl(mStateEnd); // Signal that mStillProcessing was updated mThreadState = ThreadState::Wait; mMonitor.Notify(); } dom::WorkletThread::DeleteCycleCollectedJSContext(); }
void WorkletThread::RunEventLoop(JSRuntime* aParentRuntime) { MOZ_ASSERT(!NS_IsMainThread()); PR_SetCurrentThreadName("worklet"); WorkletJSContext context(this); nsresult rv = context.Initialize(aParentRuntime); if (NS_WARN_IF(NS_FAILED(rv))) { // TODO: error propagation return; } // FIXME: JS_SetDefaultLocale // FIXME: JSSettings // FIXME: JS_SetNativeStackQuota // FIXME: JS_SetSecurityCallbacks // FIXME: JS::SetAsmJSCacheOps // FIXME: JS::SetAsyncTaskCallbacks // FIXME: JS_AddInterruptCallback // FIXME: JS::SetCTypesActivityCallback // FIXME: JS_SetGCZeal if (!JS::InitSelfHostedCode(context.Context())) { // TODO: error propagation return; } mJSContext = context.Context(); while (mJSContext) { MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(this, /* wait: */ true)); } MOZ_ASSERT(mJSContext == nullptr); }
/** * Entry point for the watchdog thread */ void RunWatchdog(void* arg) { PR_SetCurrentThreadName("Shutdown Hang Terminator"); // Let's copy and deallocate options, that's one less leak to worry // about. UniquePtr<Options> options((Options*)arg); uint32_t crashAfterTicks = options->crashAfterTicks; options = nullptr; const uint32_t timeToLive = crashAfterTicks; while (true) { // // We do not want to sleep for the entire duration, // as putting the computer to sleep would suddenly // cause us to timeout on wakeup. // // Rather, we prefer sleeping for at most 1 second // at a time. If the computer sleeps then wakes up, // we have lost at most one second, which is much // more reasonable. // #if defined(XP_WIN) Sleep(1000 /* ms */); #else usleep(1000000 /* usec */); #endif if (gHeartbeat++ < timeToLive) { continue; } // Shutdown is apparently dead. Crash the process. MOZ_CRASH("Shutdown too long, probably frozen, causing a crash."); } }
void ThreadMain(void*) { PR_SetCurrentThreadName("Hang Monitor"); MonitorAutoLock lock(*gMonitor); // In order to avoid issues with the hang monitor incorrectly triggering // during a general system stop such as sleeping, the monitor thread must // run twice to trigger hang protection. PRIntervalTime lastTimestamp = 0; int waitCount = 0; #ifdef REPORT_CHROME_HANGS Telemetry::ProcessedStack stack; int32_t systemUptime = -1; int32_t firefoxUptime = -1; auto annotations = MakeUnique<ChromeHangAnnotations>(); #endif while (true) { if (gShutdown) { return; // Exit the thread } // avoid rereading the volatile value in this loop PRIntervalTime timestamp = gTimestamp; PRIntervalTime now = PR_IntervalNow(); if (timestamp != PR_INTERVAL_NO_WAIT && now < timestamp) { // 32-bit overflow, reset for another waiting period timestamp = 1; // lowest legal PRInterval value } if (timestamp != PR_INTERVAL_NO_WAIT && timestamp == lastTimestamp && gTimeout > 0) { ++waitCount; #ifdef REPORT_CHROME_HANGS // Capture the chrome-hang stack + Firefox & system uptimes after // the minimum hang duration has been reached (not when the hang ends) if (waitCount == 2) { GetChromeHangReport(stack, systemUptime, firefoxUptime); ChromeHangAnnotatorCallout(*annotations); } #else // This is the crash-on-hang feature. // See bug 867313 for the quirk in the waitCount comparison if (waitCount >= 2) { int32_t delay = int32_t(PR_IntervalToSeconds(now - timestamp)); if (delay >= gTimeout) { MonitorAutoUnlock unlock(*gMonitor); Crash(); } } #endif } else { #ifdef REPORT_CHROME_HANGS if (waitCount >= 2) { uint32_t hangDuration = PR_IntervalToSeconds(now - lastTimestamp); Telemetry::RecordChromeHang(hangDuration, stack, systemUptime, firefoxUptime, Move(annotations)); stack.Clear(); annotations = MakeUnique<ChromeHangAnnotations>(); } #endif lastTimestamp = timestamp; waitCount = 0; } PRIntervalTime timeout; if (gTimeout <= 0) { timeout = PR_INTERVAL_NO_TIMEOUT; } else { timeout = PR_MillisecondsToInterval(gTimeout * 500); } lock.Wait(timeout); } }
void ClosingService::ThreadFunc() { PR_SetCurrentThreadName("Closing Service"); #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess()) { NuwaMarkCurrentThread(nullptr, nullptr); } #endif for (;;) { PRFileDesc *fd; { mozilla::MonitorAutoLock mon(mMonitor); while (!mShutdown && (mQueue.Length() == 0)) { mon.Wait(); } if (mShutdown) { // If we are in shutdown leak the rest of the sockets. for (uint32_t i = 0; i < mQueue.Length(); i++) { fd = mQueue[i]; // If the ClosingService layer is the first layer above // PR_NSPR_IO_LAYER we are not going to leak anything, but PR_Close // will not be called. PR_Free(fd); } mQueue.Clear(); return; } fd = mQueue[0]; mQueue.RemoveElementAt(0); } // Leave lock before closing socket. It can block for a long time and in // case we accidentally attach this layer twice this would cause deadlock. bool tcp = (PR_GetDescType(PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER)) == PR_DESC_SOCKET_TCP); PRIntervalTime closeStarted = PR_IntervalNow(); fd->methods->close(fd); // Post telemetry. if (tcp) { SendPRCloseTelemetry(closeStarted, Telemetry::PRCLOSE_TCP_BLOCKING_TIME_NORMAL, Telemetry::PRCLOSE_TCP_BLOCKING_TIME_SHUTDOWN, Telemetry::PRCLOSE_TCP_BLOCKING_TIME_CONNECTIVITY_CHANGE, Telemetry::PRCLOSE_TCP_BLOCKING_TIME_LINK_CHANGE, Telemetry::PRCLOSE_TCP_BLOCKING_TIME_OFFLINE); } else { SendPRCloseTelemetry(closeStarted, Telemetry::PRCLOSE_UDP_BLOCKING_TIME_NORMAL, Telemetry::PRCLOSE_UDP_BLOCKING_TIME_SHUTDOWN, Telemetry::PRCLOSE_UDP_BLOCKING_TIME_CONNECTIVITY_CHANGE, Telemetry::PRCLOSE_UDP_BLOCKING_TIME_LINK_CHANGE, Telemetry::PRCLOSE_UDP_BLOCKING_TIME_OFFLINE); } } }
// C-like calling sequence to glue into PR_CreateThread. void SmartCardMonitoringThread::LaunchExecute(void *arg) { PR_SetCurrentThreadName("SmartCard"); ((SmartCardMonitoringThread*)arg)->Execute(); }
void StartupCache::ThreadedWrite(void *aClosure) { PR_SetCurrentThreadName("StartupCache"); gStartupCache->WriteToDisk(); }
void ThreadMain(void*) { PR_SetCurrentThreadName("Hang Monitor"); MonitorAutoLock lock(*gMonitor); // In order to avoid issues with the hang monitor incorrectly triggering // during a general system stop such as sleeping, the monitor thread must // run twice to trigger hang protection. PRIntervalTime lastTimestamp = 0; int waitCount = 0; #ifdef REPORT_CHROME_HANGS Telemetry::ProcessedStack stack; #endif while (true) { if (gShutdown) { return; // Exit the thread } // avoid rereading the volatile value in this loop PRIntervalTime timestamp = gTimestamp; PRIntervalTime now = PR_IntervalNow(); if (timestamp != PR_INTERVAL_NO_WAIT && now < timestamp) { // 32-bit overflow, reset for another waiting period timestamp = 1; // lowest legal PRInterval value } if (timestamp != PR_INTERVAL_NO_WAIT && timestamp == lastTimestamp && gTimeout > 0) { ++waitCount; if (waitCount == 2) { #ifdef REPORT_CHROME_HANGS GetChromeHangReport(stack); #else int32_t delay = int32_t(PR_IntervalToSeconds(now - timestamp)); if (delay > gTimeout) { MonitorAutoUnlock unlock(*gMonitor); Crash(); } #endif } } else { #ifdef REPORT_CHROME_HANGS if (waitCount >= 2) { uint32_t hangDuration = PR_IntervalToSeconds(now - lastTimestamp); Telemetry::RecordChromeHang(hangDuration, stack); stack.Clear(); } #endif lastTimestamp = timestamp; waitCount = 0; } PRIntervalTime timeout; if (gTimeout <= 0) { timeout = PR_INTERVAL_NO_TIMEOUT; } else { timeout = PR_MillisecondsToInterval(gTimeout * 500); } lock.Wait(timeout); } }
void RunWriter(void* arg) { PR_SetCurrentThreadName("Shutdown Statistics Writer"); MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(arg); // Shutdown will generally complete before we have a chance to // deallocate. This is not a leak. // Setup destinationPath and tmpFilePath nsCString destinationPath(static_cast<char*>(arg)); nsAutoCString tmpFilePath; tmpFilePath.Append(destinationPath); tmpFilePath.AppendLiteral(".tmp"); // Cleanup any file leftover from a previous run Unused << PR_Delete(tmpFilePath.get()); Unused << PR_Delete(destinationPath.get()); while (true) { // // Check whether we have received data from the main thread. // // We perform the check before waiting on `gWriteReady` as we may // have received data while we were busy writing. // // Also note that gWriteData may have been modified several times // since we last checked. That's ok, we are not losing any important // data (since we keep adding data), and we are not leaking memory // (since the main thread deallocates any data that hasn't been // consumed by the writer thread). // UniquePtr<nsCString> data(gWriteData.exchange(nullptr)); if (!data) { // Data is not available yet. // Wait until the main thread provides it. PR_EnterMonitor(gWriteReady); PR_Wait(gWriteReady, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(gWriteReady); continue; } MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(data.get()); // Shutdown may complete before we have a chance to deallocate. // This is not a leak. // // Write to a temporary file // // In case of any error, we simply give up. Since the data is // hardly critical, we don't want to spend too much effort // salvaging it. // UniquePtr<PRFileDesc, PR_CloseDelete> tmpFileDesc(PR_Open(tmpFilePath.get(), PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE, 00600)); // Shutdown may complete before we have a chance to close the file. // This is not a leak. MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(tmpFileDesc.get()); if (tmpFileDesc == nullptr) { break; } if (PR_Write(tmpFileDesc.get(), data->get(), data->Length()) == -1) { break; } tmpFileDesc.reset(); // // Rename on top of destination file. // // This is not sufficient to guarantee that the destination file // will be written correctly, but, again, we don't care enough // about the data to make more efforts. // if (PR_Rename(tmpFilePath.get(), destinationPath.get()) != PR_SUCCESS) { break; } } }
NS_IMETHODIMP LSPAnnotationGatherer::Run() { PR_SetCurrentThreadName("LSP Annotator"); mThread = NS_GetCurrentThread(); DWORD size = 0; int err; // Get the size of the buffer we need if (SOCKET_ERROR != WSCEnumProtocols(nullptr, nullptr, &size, &err) || err != WSAENOBUFS) { // Er, what? NS_NOTREACHED("WSCEnumProtocols suceeded when it should have failed ..."); return NS_ERROR_FAILURE; } auto byteArray = MakeUnique<char[]>(size); WSAPROTOCOL_INFOW* providers = reinterpret_cast<WSAPROTOCOL_INFOW*>(byteArray.get()); int n = WSCEnumProtocols(nullptr, providers, &size, &err); if (n == SOCKET_ERROR) { // Lame. We provided the right size buffer; we'll just give up now. NS_WARNING("Could not get LSP list"); return NS_ERROR_FAILURE; } nsCString str; for (int i = 0; i < n; i++) { AppendUTF16toUTF8(nsDependentString(providers[i].szProtocol), str); str.AppendLiteral(" : "); str.AppendInt(providers[i].iVersion); str.AppendLiteral(" : "); str.AppendInt(providers[i].iAddressFamily); str.AppendLiteral(" : "); str.AppendInt(providers[i].iSocketType); str.AppendLiteral(" : "); str.AppendInt(providers[i].iProtocol); str.AppendLiteral(" : "); str.AppendPrintf("0x%x", providers[i].dwServiceFlags1); str.AppendLiteral(" : "); str.AppendPrintf("0x%x", providers[i].dwProviderFlags); str.AppendLiteral(" : "); wchar_t path[MAX_PATH]; int pathLen = MAX_PATH; if (!WSCGetProviderPath(&providers[i].ProviderId, path, &pathLen, &err)) { AppendUTF16toUTF8(nsDependentString(path), str); } str.AppendLiteral(" : "); // If WSCGetProviderInfo is available, we should call it to obtain the // category flags for this provider. When present, these flags inform // Windows as to which order to chain the providers. nsModuleHandle ws2_32(LoadLibraryW(L"ws2_32.dll")); if (ws2_32) { decltype(WSCGetProviderInfo)* pWSCGetProviderInfo = reinterpret_cast<decltype(WSCGetProviderInfo)*>( GetProcAddress(ws2_32, "WSCGetProviderInfo")); if (pWSCGetProviderInfo) { DWORD categoryInfo; size_t categoryInfoSize = sizeof(categoryInfo); if (!pWSCGetProviderInfo(&providers[i].ProviderId, ProviderInfoLspCategories, (PBYTE)&categoryInfo, &categoryInfoSize, 0, &err)) { str.AppendPrintf("0x%x", categoryInfo); } } } str.AppendLiteral(" : "); if (providers[i].ProtocolChain.ChainLen <= BASE_PROTOCOL) { // If we're dealing with a catalog entry that identifies an individual // base or layer provider, log its provider GUID. RPC_CSTR provIdStr = nullptr; if (UuidToStringA(&providers[i].ProviderId, &provIdStr) == RPC_S_OK) { str.Append(reinterpret_cast<char*>(provIdStr)); RpcStringFreeA(&provIdStr); } } if (i + 1 != n) { str.AppendLiteral(" \n "); } } mString = str; NS_DispatchToMainThread(NewRunnableMethod(this, &LSPAnnotationGatherer::Annotate)); return NS_OK; }
NS_IMETHODIMP AudioRunnable::Run() { PR_SetCurrentThreadName("Android Audio"); JNIEnv* jenv = GetJNIForThread(); if (!jenv) return NS_ERROR_FAILURE; mozilla::AutoLocalJNIFrame autoFrame(jenv, 2); jbyteArray bytearray = jenv->NewByteArray(mTrack->bufferSize); if (!bytearray) { LOG("AudioRunnable:: Run. Could not create bytearray"); return NS_ERROR_FAILURE; } jbyte *byte = jenv->GetByteArrayElements(bytearray, NULL); if (!byte) { LOG("AudioRunnable:: Run. Could not create bytearray"); return NS_ERROR_FAILURE; } ANPAudioBuffer buffer; buffer.channelCount = mTrack->channels; buffer.format = mTrack->format; buffer.bufferData = (void*) byte; while (true) { // reset the buffer size buffer.size = mTrack->bufferSize; { mozilla::MutexAutoLock lock(mTrack->lock); if (!mTrack->keepGoing) break; // Get data from the plugin mTrack->proc(kMoreData_ANPAudioEvent, mTrack->user, &buffer); } if (buffer.size == 0) { LOG("%p - kMoreData_ANPAudioEvent", mTrack); continue; } size_t wroteSoFar = 0; jint retval; do { retval = jenv->CallIntMethod(mTrack->output_unit, at.write, bytearray, wroteSoFar, buffer.size - wroteSoFar); if (retval < 0) { LOG("%p - Write failed %d", mTrack, retval); break; } wroteSoFar += retval; } while(wroteSoFar < buffer.size); } jenv->CallVoidMethod(mTrack->output_unit, at.release); jenv->DeleteGlobalRef(mTrack->output_unit); jenv->DeleteGlobalRef(mTrack->at_class); delete mTrack; jenv->ReleaseByteArrayElements(bytearray, byte, 0); return NS_OK; }
NS_IMETHODIMP nsNameThreadRunnable::Run() { PR_SetCurrentThreadName(mName.BeginReading()); return NS_OK; }