void SignalPipeWatcher::StopWatching() { MOZ_ASSERT(XRE_GetIOMessageLoop() == MessageLoopForIO::current()); // Close sDumpPipeWriteFd /after/ setting the fd to -1. // Otherwise we have the (admittedly far-fetched) race where we // // 1) close sDumpPipeWriteFd // 2) open a new fd with the same number as sDumpPipeWriteFd // had. // 3) receive a signal, then write to the fd. int pipeWriteFd = sDumpPipeWriteFd.exchange(-1); close(pipeWriteFd); FdWatcher::StopWatching(); }
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; } } }
MemoryPressureState NS_GetPendingMemoryPressure() { int32_t value = sMemoryPressurePending.exchange(MemPressure_None); return MemoryPressureState(value); }