Commit ec9eb0bc authored by Marian-Vasile Laza's avatar Marian-Vasile Laza
Browse files

Backed out changeset ace627c97884 (bug 1687843) for causing Bug 1715414. CLOSED TREE

parent 1fc0882e
Loading
Loading
Loading
Loading
+8 −15
Original line number Diff line number Diff line
@@ -2188,14 +2188,11 @@ void ContentChild::ActorDestroy(ActorDestroyReason why) {

  mIdleObservers.Clear();

  if (mConsoleListener) {
    nsCOMPtr<nsIConsoleService> svc(
        do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  if (svc) {
    svc->UnregisterListener(mConsoleListener);
    mConsoleListener->mChild = nullptr;
  }
  }
  mIsAlive = false;

  CrashReporterClient::DestroySingleton();
@@ -2593,21 +2590,17 @@ mozilla::ipc::IPCResult ContentChild::RecvAppInfo(

mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
    const nsCString& aRemoteType) {
  if (aRemoteType == mRemoteType) {
    // Allocation of preallocated processes that are still launching can
    // cause this
    return IPC_OK();
  }

  if (!mRemoteType.IsVoid()) {
    // Preallocated processes are type PREALLOC_REMOTE_TYPE; they can become
    // anything except a File: process.
    MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
            ("Changing remoteType of process %d from %s to %s", getpid(),
             mRemoteType.get(), aRemoteType.get()));
    // prealloc->anything (but file) or web->web allowed, and no-change
    // prealloc->anything (but file) or web->web allowed
    MOZ_RELEASE_ASSERT(aRemoteType != FILE_REMOTE_TYPE &&
                       mRemoteType == PREALLOC_REMOTE_TYPE);
                       (mRemoteType == PREALLOC_REMOTE_TYPE ||
                        (mRemoteType == DEFAULT_REMOTE_TYPE &&
                         aRemoteType == DEFAULT_REMOTE_TYPE)));
  } else {
    // Initial setting of remote type.  Either to 'prealloc' or the actual
    // final type (if we didn't use a preallocated process)
+60 −75
Original line number Diff line number Diff line
@@ -663,10 +663,13 @@ static const char* sObserverTopics[] = {

// PreallocateProcess is called by the PreallocatedProcessManager.
// ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
/*static*/ already_AddRefed<ContentParent>
ContentParent::MakePreallocProcess() {
/*static*/ RefPtr<ContentParent::LaunchPromise>
ContentParent::PreallocateProcess() {
  RefPtr<ContentParent> process = new ContentParent(PREALLOC_REMOTE_TYPE);
  return process.forget();

  MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
          ("Preallocating process of type prealloc"));
  return process->LaunchSubprocessAsync(PROCESS_PRIORITY_PREALLOC);
}

/*static*/
@@ -908,7 +911,7 @@ static already_AddRefed<nsIPrincipal> CreateRemoteTypeIsolationPrincipal(
/*static*/
already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
    const nsACString& aRemoteType, nsTArray<ContentParent*>& aContentParents,
    uint32_t aMaxContentParents, bool aPreferUsed, ProcessPriority aPriority) {
    uint32_t aMaxContentParents, bool aPreferUsed) {
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
  AutoRestore ar(sInProcessSelector);
  sInProcessSelector = true;
@@ -983,7 +986,6 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
  }

  // Try to take a preallocated process except for certain remote types.
  // Note: this process may not have finished launching yet
  RefPtr<ContentParent> preallocated;
  if (aRemoteType != FILE_REMOTE_TYPE &&
      aRemoteType != EXTENSION_REMOTE_TYPE &&  // Bug 1638119
@@ -994,33 +996,24 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
    preallocated->AssertAlive();

    if (profiler_thread_is_being_profiled()) {
      nsPrintfCString marker(
          "Assigned preallocated process %u%s",
          (unsigned int)preallocated->ChildID(),
          preallocated->IsLaunching() ? " (still launching)" : "");
      nsPrintfCString marker("Assigned preallocated process %u",
                             (unsigned int)preallocated->ChildID());
      PROFILER_MARKER_TEXT("Process", DOM, {}, marker);
    }
    MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
            ("Adopted preallocated process %p for type %s%s",
             preallocated.get(), PromiseFlatCString(aRemoteType).get(),
             preallocated->IsLaunching() ? " (still launching)" : ""));
            ("Adopted preallocated process %p for type %s", preallocated.get(),
             PromiseFlatCString(aRemoteType).get()));

    // This ensures that the preallocator won't shut down the process once
    // it finishes starting
    preallocated->mRemoteType.Assign(aRemoteType);
    preallocated->mRemoteTypeIsolationPrincipal =
        CreateRemoteTypeIsolationPrincipal(aRemoteType);
    // Specialize this process for the appropriate remote type, and activate it.
    preallocated->mActivateTS = TimeStamp::Now();
    preallocated->AddToPool(aContentParents);

    // rare, but will happen
    if (!preallocated->IsLaunching()) {
      // Specialize this process for the appropriate remote type, and activate
      // it.
    preallocated->mRemoteType.Assign(aRemoteType);
    preallocated->mRemoteTypeIsolationPrincipal =
        CreateRemoteTypeIsolationPrincipal(aRemoteType);
    Unused << preallocated->SendRemoteType(preallocated->mRemoteType);

      nsCOMPtr<nsIObserverService> obs =
          mozilla::services::GetObserverService();
    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    if (obs) {
      nsAutoString cpId;
      cpId.AppendInt(static_cast<uint64_t>(preallocated->ChildID()));
@@ -1028,7 +1021,6 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
                           "process-type-set", cpId.get());
      preallocated->AssertAlive();
    }
    }
    return preallocated.forget();
  }

@@ -1073,10 +1065,23 @@ ContentParent::GetNewOrUsedLaunchingBrowserProcess(
  }

  // Let's try and reuse an existing process.
  contentParent = GetUsedBrowserProcess(
      aRemoteType, contentParents, maxContentParents, aPreferUsed, aPriority);
  contentParent = GetUsedBrowserProcess(aRemoteType, contentParents,
                                        maxContentParents, aPreferUsed);

  if (contentParent) {
    // We have located a process. It may not have finished initializing,
    // this will be for the caller to handle.
    MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
            ("GetNewOrUsedProcess: Used process %p (launching %d)",
             contentParent.get(), contentParent->IsLaunching()));
    contentParent->AssertAlive();
    contentParent->StopRecycling();
    if (aGroup) {
      aGroup->EnsureHostProcess(contentParent);
    }
    return contentParent.forget();
  }

  if (!contentParent) {
  // No reusable process. Let's create and launch one.
  // The life cycle will be set to `LifecycleState::LAUNCHING`.
  MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
@@ -1089,22 +1094,18 @@ ContentParent::GetNewOrUsedLaunchingBrowserProcess(
    contentParent->LaunchSubprocessReject();
    return nullptr;
  }
  // Store this process for future reuse.
  contentParent->AddToPool(contentParents);

  // Until the new process is ready let's not allow to start up any
  // preallocated processes. The blocker will be removed once we receive
  // the first idle message.
  contentParent->mIsAPreallocBlocker = true;
  PreallocatedProcessManager::AddBlocker(aRemoteType, contentParent);

    // Store this process for future reuse.
    contentParent->AddToPool(contentParents);

    MOZ_LOG(
        ContentParent::GetLog(), LogLevel::Debug,
        ("GetNewOrUsedProcess: new immediate process %p", contentParent.get()));
  }
  // else we have an existing or preallocated process (which may be
  // still launching)

  MOZ_ASSERT(contentParent->IsLaunching());
  MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
          ("GetNewOrUsedProcess: new process %p", contentParent.get()));
  contentParent->AssertAlive();
  contentParent->StopRecycling();
  if (aGroup) {
@@ -1146,8 +1147,6 @@ RefPtr<ContentParent::LaunchPromise> ContentParent::WaitForLaunchAsync(
    ProcessPriority aPriority) {
  MOZ_DIAGNOSTIC_ASSERT(!IsDead());
  if (!IsLaunching()) {
    MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
            ("WaitForLaunchAsync: launched"));
    return LaunchPromise::CreateAndResolve(this, __func__);
  }

@@ -1162,8 +1161,6 @@ RefPtr<ContentParent::LaunchPromise> ContentParent::WaitForLaunchAsync(
      GetCurrentSerialEventTarget(), __func__,
      [self = RefPtr{this}, aPriority] {
        if (self->LaunchSubprocessResolve(/* aIsSync = */ false, aPriority)) {
          MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
                  ("WaitForLaunchAsync: async, now launched"));
          self->mActivateTS = TimeStamp::Now();
          return LaunchPromise::CreateAndResolve(self, __func__);
        }
@@ -1172,8 +1169,6 @@ RefPtr<ContentParent::LaunchPromise> ContentParent::WaitForLaunchAsync(
        return LaunchPromise::CreateAndReject(LaunchError(), __func__);
      },
      [self = RefPtr{this}] {
        MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
                ("WaitForLaunchAsync: async, rejected"));
        self->LaunchSubprocessReject();
        return LaunchPromise::CreateAndReject(LaunchError(), __func__);
      });
@@ -1732,8 +1727,7 @@ void ContentParent::Init() {
void ContentParent::MaybeBeginShutDown(uint32_t aExpectedBrowserCount,
                                       bool aSendShutDown) {
  MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
          ("MaybeBeginShutdown %p, %u vs %u", this,
           ManagedPBrowserParent().Count(), aExpectedBrowserCount));
          ("MaybeBeginShutdown %p", this));
  MOZ_ASSERT(NS_IsMainThread());

  if (ManagedPBrowserParent().Count() != aExpectedBrowserCount ||
@@ -1783,8 +1777,6 @@ void ContentParent::MaybeAsyncSendShutDownMessage() {
}

void ContentParent::ShutDownProcess(ShutDownMethod aMethod) {
  MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
          ("ShutDownProcess: %p", this));
  // NB: must MarkAsDead() here so that this isn't accidentally
  // returned from Get*() while in the midst of shutdown.
  MarkAsDead();
@@ -2294,8 +2286,6 @@ bool ContentParent::ShouldKeepProcessAlive() {
}

void ContentParent::NotifyTabDestroying() {
  MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
          ("NotifyTabDestroying %p:", this));
  // There can be more than one PBrowser for a given app process
  // because of popup windows.  PBrowsers can also destroy
  // concurrently.  When all the PBrowsers are destroying, kick off
@@ -2569,8 +2559,6 @@ bool ContentParent::BeginSubprocessLaunch(ProcessPriority aPriority) {

void ContentParent::LaunchSubprocessReject() {
  NS_ERROR("failed to launch child in the parent");
  MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
          ("failed to launch child in the parent"));
  // Now that communication with the child is complete, we can cleanup
  // the preference serializer.
  mPrefSerializer = nullptr;
@@ -3426,9 +3414,6 @@ mozilla::ipc::IPCResult ContentParent::RecvFirstIdle() {
  // which we use as a good time to signal the PreallocatedProcessManager
  // that it can start allocating processes from now on.
  if (mIsAPreallocBlocker) {
    MOZ_LOG(
        ContentParent::GetLog(), LogLevel::Verbose,
        ("RecvFirstIdle %p: Removing Blocker for %s", this, mRemoteType.get()));
    PreallocatedProcessManager::RemoveBlocker(mRemoteType, this);
    mIsAPreallocBlocker = false;
  }
@@ -4094,9 +4079,9 @@ void ContentParent::KillHard(const char* aReason) {
  if (mSubprocess) {
    MOZ_LOG(
        ContentParent::GetLog(), LogLevel::Verbose,
        ("KillHard Subprocess(%s): ContentParent %p mSubprocess %p handle "
        ("KillHard Subprocess: ContentParent %p mSubprocess %p handle "
         "%" PRIuPTR,
         aReason, this, mSubprocess,
         this, mSubprocess,
         mSubprocess ? (uintptr_t)mSubprocess->GetChildProcessHandle() : -1));
    mSubprocess->SetAlreadyDead();
  }
+3 −3
Original line number Diff line number Diff line
@@ -152,9 +152,9 @@ class ContentParent final
  static LogModule* GetLog();

  /**
   * Create a ContentParent suitable for use later as a content process.
   * Create a subprocess suitable for use later as a content process.
   */
  static already_AddRefed<ContentParent> MakePreallocProcess();
  static RefPtr<LaunchPromise> PreallocateProcess();

  /**
   * Start up the content-process machinery.  This might include
@@ -1446,7 +1446,7 @@ class ContentParent final
  // Return an existing ContentParent if possible. Otherwise, `nullptr`.
  static already_AddRefed<ContentParent> GetUsedBrowserProcess(
      const nsACString& aRemoteType, nsTArray<ContentParent*>& aContentParents,
      uint32_t aMaxContentParents, bool aPreferUsed, ProcessPriority aPriority);
      uint32_t aMaxContentParents, bool aPreferUsed);

  void AddToPool(nsTArray<ContentParent*>&);
  void RemoveFromPool(nsTArray<ContentParent*>&);
+71 −70
Original line number Diff line number Diff line
@@ -17,8 +17,8 @@
#include "ProcessPriorityManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIXULRuntime.h"
#include "nsTArray.h"
#include "prsystem.h"
#include <deque>

using namespace mozilla::hal;
using namespace mozilla::dom;
@@ -68,12 +68,15 @@ class PreallocatedProcessManagerImpl final : public nsIObserver {
  void Disable();
  void CloseProcesses();

  bool IsEmpty() const { return mPreallocatedProcesses.IsEmpty(); }
  bool IsEmpty() const {
    return mPreallocatedProcesses.empty() && !mLaunchInProgress;
  }

  bool mEnabled;
  static bool sShutdown;
  bool mLaunchInProgress;
  uint32_t mNumberPreallocs;
  AutoTArray<RefPtr<ContentParent>, 3> mPreallocatedProcesses;
  std::deque<RefPtr<ContentParent>> mPreallocatedProcesses;
  // Even if we have multiple PreallocatedProcessManagerImpls, we'll have
  // one blocker counter
  static uint32_t sNumBlockers;
@@ -109,12 +112,12 @@ PreallocatedProcessManagerImpl* PreallocatedProcessManagerImpl::Singleton() {
NS_IMPL_ISUPPORTS(PreallocatedProcessManagerImpl, nsIObserver)

PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
    : mEnabled(false), mNumberPreallocs(1) {}
    : mEnabled(false), mLaunchInProgress(false), mNumberPreallocs(1) {}

PreallocatedProcessManagerImpl::~PreallocatedProcessManagerImpl() {
  // Note: mPreallocatedProcesses may not be null, but all processes should
  // be dead (IsDead==true).  We block Erase() when our observer sees
  // shutdown starting.
  // This shouldn't happen, because the promise callbacks should
  // hold strong references, but let't make absolutely sure:
  MOZ_RELEASE_ASSERT(!mLaunchInProgress);
}

void PreallocatedProcessManagerImpl::Init() {
@@ -185,7 +188,7 @@ void PreallocatedProcessManagerImpl::RereadPrefs() {
    if (number >= 0) {
      Enable(number);
      // We have one prealloc queue for all types except File now
      if (static_cast<uint64_t>(number) < mPreallocatedProcesses.Length()) {
      if (static_cast<uint64_t>(number) < mPreallocatedProcesses.size()) {
        CloseProcesses();
      }
    }
@@ -200,36 +203,31 @@ already_AddRefed<ContentParent> PreallocatedProcessManagerImpl::Take(
    return nullptr;
  }
  RefPtr<ContentParent> process;
  if (!IsEmpty()) {
    process = mPreallocatedProcesses.ElementAt(0);
    mPreallocatedProcesses.RemoveElementAt(0);
  if (!mPreallocatedProcesses.empty()) {
    process = mPreallocatedProcesses.front().forget();
    mPreallocatedProcesses.pop_front();  // holds a nullptr

    // Don't set the priority to FOREGROUND here, since it may not have
    // finished starting
    ProcessPriorityManager::SetProcessPriority(process,
                                               PROCESS_PRIORITY_FOREGROUND);

    // We took a preallocated process. Let's try to start up a new one
    // soon.
    ContentParent* last = mPreallocatedProcesses.SafeLastElement(nullptr);
    // There could be a launching process that isn't the last, but that's
    // ok (and unlikely)
    if (!last || !last->IsLaunching()) {
    AllocateAfterDelay();
    }
    MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
            ("Use prealloc process %p%s, %lu available", process.get(),
             process->IsLaunching() ? " (still launching)" : "",
             (unsigned long)mPreallocatedProcesses.Length()));
            ("Use prealloc process %p", process.get()));
  }
  if (process && !process->IsLaunching()) {
    ProcessPriorityManager::SetProcessPriority(process,
                                               PROCESS_PRIORITY_FOREGROUND);
  }  // else this will get set by the caller when they call InitInternal()

  return process.forget();
}

void PreallocatedProcessManagerImpl::Erase(ContentParent* aParent) {
  (void)mPreallocatedProcesses.RemoveElement(aParent);
  // Ensure this ContentParent isn't cached
  for (auto it = mPreallocatedProcesses.begin();
       it != mPreallocatedProcesses.end(); it++) {
    if (*it == aParent) {
      mPreallocatedProcesses.erase(it);
      break;
    }
  }
}

void PreallocatedProcessManagerImpl::Enable(uint32_t aProcesses) {
@@ -274,7 +272,7 @@ void PreallocatedProcessManagerImpl::RemoveBlocker(ContentParent* aParent) {

bool PreallocatedProcessManagerImpl::CanAllocate() {
  return mEnabled && sNumBlockers == 0 &&
         mPreallocatedProcesses.Length() < mNumberPreallocs && !sShutdown &&
         mPreallocatedProcesses.size() < mNumberPreallocs && !sShutdown &&
         (FissionAutostart() ||
          !ContentParent::IsMaxProcessCountReached(DEFAULT_REMOTE_TYPE));
}
@@ -317,19 +315,15 @@ void PreallocatedProcessManagerImpl::AllocateNow() {
    return;
  }

  RefPtr<ContentParent> process = ContentParent::MakePreallocProcess();
  mPreallocatedProcesses.AppendElement(process);
  MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
          ("Preallocated = %lu of %d processes",
           (unsigned long)mPreallocatedProcesses.Length(), mNumberPreallocs));

  RefPtr<PreallocatedProcessManagerImpl> self(this);
  process->LaunchSubprocessAsync(PROCESS_PRIORITY_PREALLOC)
      ->Then(
  mLaunchInProgress = true;

  ContentParent::PreallocateProcess()->Then(
      GetCurrentSerialEventTarget(), __func__,
          [self, this, process](const RefPtr<ContentParent>&) {

      [self, this](const RefPtr<ContentParent>& process) {
        mLaunchInProgress = false;
        if (process->IsDead()) {
              Erase(process);
          // Process died in startup (before we could add it).  If it
          // dies after this, MarkAsDead() will Erase() this entry.
          // Shouldn't be in the sBrowserContentParents, so we don't need
@@ -338,24 +332,31 @@ void PreallocatedProcessManagerImpl::AllocateNow() {
          // causing them to consistently fail; if everything is ok on the
          // next allocation request we'll kick off creation.
        } else {
              // Continue prestarting processes if needed
          if (CanAllocate()) {
                if (mPreallocatedProcesses.Length() < mNumberPreallocs) {
            // slight perf reason for push_back - while the cpu cache
            // probably has stack/etc associated with the most recent
            // process created, we don't know that it has finished startup.
            // If we added it to the queue on completion of startup, we
            // could push_front it, but that would require a bunch more
            // logic.
            mPreallocatedProcesses.push_back(process);
            MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
                    ("Preallocated = %lu of %d processes",
                     (unsigned long)mPreallocatedProcesses.size(),
                     mNumberPreallocs));

            // Continue prestarting processes if needed
            if (mPreallocatedProcesses.size() < mNumberPreallocs) {
              AllocateOnIdle();
            }
              } else if (!mEnabled || sShutdown) {
                // if this has a remote type set, it's been allocated for use
                // already
                if (process->mRemoteType == PREALLOC_REMOTE_TYPE) {
                  // This will Erase() it
                  process->ShutDownProcess(
                      ContentParent::SEND_SHUTDOWN_MESSAGE);
                }
          } else {
            process->ShutDownProcess(ContentParent::SEND_SHUTDOWN_MESSAGE);
          }
        }
      },
          [self, this, process](ContentParent::LaunchError) {
            Erase(process);

      [self, this](ContentParent::LaunchError err) {
        mLaunchInProgress = false;
      });
}

@@ -369,9 +370,9 @@ void PreallocatedProcessManagerImpl::Disable() {
}

void PreallocatedProcessManagerImpl::CloseProcesses() {
  while (!IsEmpty()) {
    RefPtr<ContentParent> process(mPreallocatedProcesses.ElementAt(0));
    mPreallocatedProcesses.RemoveElementAt(0);
  while (!mPreallocatedProcesses.empty()) {
    RefPtr<ContentParent> process(mPreallocatedProcesses.front().forget());
    mPreallocatedProcesses.pop_front();
    process->ShutDownProcess(ContentParent::SEND_SHUTDOWN_MESSAGE);
    // drop ref and let it free
  }