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();
 }
Beispiel #8
0
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();
}
Beispiel #11
0
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();
}
Beispiel #12
0
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);
}
Beispiel #13
0
/**
 * 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.");
  }
}
Beispiel #14
0
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);
  }
}
Beispiel #19
0
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;
    }
  }
}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
NS_IMETHODIMP
nsNameThreadRunnable::Run()
{
  PR_SetCurrentThreadName(mName.BeginReading());
  return NS_OK;
}