зеркало из https://github.com/mozilla/gecko-dev.git
Implement GPU process shutdown. (bug 1271180 part 5, r=billm)
--HG-- extra : rebase_source : c00e110f584ac056cc4e7918b833d6c6dbd79007
This commit is contained in:
Родитель
d2678d4141
Коммит
a6676c7cfb
|
@ -4,11 +4,13 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "GPUChild.h"
|
||||
#include "GPUProcessHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
GPUChild::GPUChild()
|
||||
GPUChild::GPUChild(GPUProcessHost* aHost)
|
||||
: mHost(aHost)
|
||||
{
|
||||
MOZ_COUNT_CTOR(GPUChild);
|
||||
}
|
||||
|
@ -18,5 +20,33 @@ GPUChild::~GPUChild()
|
|||
MOZ_COUNT_DTOR(GPUChild);
|
||||
}
|
||||
|
||||
void
|
||||
GPUChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mHost->OnChannelClosed();
|
||||
}
|
||||
|
||||
class DeferredDeleteGPUChild : public Runnable
|
||||
{
|
||||
public:
|
||||
explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
|
||||
: mChild(Move(aChild))
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP Run() override {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<GPUChild> mChild;
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
GPUChild::Destroy(UniquePtr<GPUChild>&& aChild)
|
||||
{
|
||||
NS_DispatchToMainThread(new DeferredDeleteGPUChild(Move(aChild)));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,15 +7,25 @@
|
|||
#define _include_mozilla_gfx_ipc_GPUChild_h_
|
||||
|
||||
#include "mozilla/gfx/PGPUChild.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class GPUProcessHost;
|
||||
|
||||
class GPUChild final : public PGPUChild
|
||||
{
|
||||
public:
|
||||
GPUChild();
|
||||
GPUChild(GPUProcessHost* aHost);
|
||||
~GPUChild();
|
||||
|
||||
static void Destroy(UniquePtr<GPUChild>&& aChild);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
GPUProcessHost* mHost;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -35,7 +35,7 @@ GPUParent::Init(base::ProcessId aParentPid,
|
|||
}
|
||||
|
||||
bool
|
||||
GPUParent::RecvBeginShutdown()
|
||||
GPUParent::RecvNothing()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -48,7 +48,14 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
|
|||
ProcessChild::QuickExit();
|
||||
}
|
||||
|
||||
#ifndef NS_FREE_PERMANENT_DATA
|
||||
// No point in going through XPCOM shutdown because we don't keep persistent
|
||||
// state. Currently we quick-exit in RecvBeginShutdown so this should be
|
||||
// unreachable.
|
||||
ProcessChild::QuickExit();
|
||||
#else
|
||||
XRE_ShutdownChildProcess();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -21,7 +21,7 @@ public:
|
|||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel);
|
||||
|
||||
bool RecvBeginShutdown() override;
|
||||
bool RecvNothing() override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
};
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gfxPrefs.h"
|
||||
#include "GPUProcessHost.h"
|
||||
#include "chrome/common/process_watcher.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -15,7 +17,8 @@ GPUProcessHost::GPUProcessHost(Listener* aListener)
|
|||
: GeckoChildProcessHost(GeckoProcessType_GPU),
|
||||
mListener(aListener),
|
||||
mTaskFactory(this),
|
||||
mLaunchPhase(LaunchPhase::Unlaunched)
|
||||
mLaunchPhase(LaunchPhase::Unlaunched),
|
||||
mShutdownRequested(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(GPUProcessHost);
|
||||
}
|
||||
|
@ -115,7 +118,7 @@ GPUProcessHost::InitAfterConnect(bool aSucceeded)
|
|||
mLaunchPhase = LaunchPhase::Complete;
|
||||
|
||||
if (aSucceeded) {
|
||||
mGPUChild = MakeUnique<GPUChild>();
|
||||
mGPUChild = MakeUnique<GPUChild>(this);
|
||||
DebugOnly<bool> rv =
|
||||
mGPUChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
|
||||
MOZ_ASSERT(rv);
|
||||
|
@ -129,10 +132,66 @@ GPUProcessHost::InitAfterConnect(bool aSucceeded)
|
|||
void
|
||||
GPUProcessHost::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(!mShutdownRequested);
|
||||
|
||||
mListener = nullptr;
|
||||
|
||||
if (mGPUChild) {
|
||||
// OnChannelClosed uses this to check if the shutdown was expected or
|
||||
// unexpected.
|
||||
mShutdownRequested = true;
|
||||
|
||||
#ifdef NS_FREE_PERMANENT_DATA
|
||||
mGPUChild->Close();
|
||||
#else
|
||||
// No need to communicate shutdown, the GPU process doesn't need to
|
||||
// communicate anything back.
|
||||
KillHard("NormalShutdown");
|
||||
#endif
|
||||
|
||||
// Wait for ActorDestroy.
|
||||
return;
|
||||
}
|
||||
|
||||
DestroyProcess();
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessHost::OnChannelClosed()
|
||||
{
|
||||
if (!mShutdownRequested) {
|
||||
// This is an unclean shutdown. Notify our listener that we're going away.
|
||||
if (mListener) {
|
||||
mListener->OnProcessUnexpectedShutdown(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Release the actor.
|
||||
GPUChild::Destroy(Move(mGPUChild));
|
||||
MOZ_ASSERT(!mGPUChild);
|
||||
|
||||
// If the owner of GPUProcessHost already requested shutdown, we can now
|
||||
// schedule destruction. Otherwise we must wait for someone to call
|
||||
// Shutdown. Note that GPUProcessManager calls Shutdown within
|
||||
// OnProcessUnexpectedShutdown.
|
||||
if (mShutdownRequested) {
|
||||
DestroyProcess();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessHost::KillHard(const char* aReason)
|
||||
{
|
||||
ProcessHandle handle = GetChildProcessHandle();
|
||||
if (!base::KillProcess(handle, base::PROCESS_END_KILLED_BY_USER, false)) {
|
||||
NS_WARNING("failed to kill subprocess!");
|
||||
}
|
||||
|
||||
SetAlreadyDead();
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated, handle, /*force=*/true));
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessHost::DestroyProcess()
|
||||
{
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/ipc/TaskFactory.h"
|
||||
|
||||
class nsITimer;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
|
@ -27,11 +30,19 @@ class GPUChild;
|
|||
// at a time due to its shutdown being asynchronous.
|
||||
class GPUProcessHost final : public ipc::GeckoChildProcessHost
|
||||
{
|
||||
friend class GPUChild;
|
||||
|
||||
public:
|
||||
class Listener {
|
||||
public:
|
||||
virtual void OnProcessLaunchComplete(GPUProcessHost* aHost)
|
||||
{}
|
||||
|
||||
// The GPUProcessHost has unexpectedly shutdown or had its connection
|
||||
// severed. This is not called if an error occurs after calling
|
||||
// Shutdown().
|
||||
virtual void OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
|
||||
{}
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -71,6 +82,8 @@ public:
|
|||
void OnChannelConnected(int32_t peer_pid) override;
|
||||
void OnChannelError() override;
|
||||
|
||||
void SetListener(Listener* aListener);
|
||||
|
||||
private:
|
||||
// Called on the main thread.
|
||||
void OnChannelConnectedTask();
|
||||
|
@ -79,6 +92,12 @@ private:
|
|||
// Called on the main thread after a connection has been established.
|
||||
void InitAfterConnect(bool aSucceeded);
|
||||
|
||||
// Called on the main thread when the mGPUChild actor is shutting down.
|
||||
void OnChannelClosed();
|
||||
|
||||
// Kill the remote process, triggering IPC shutdown.
|
||||
void KillHard(const char* aReason);
|
||||
|
||||
void DestroyProcess();
|
||||
|
||||
private:
|
||||
|
@ -95,6 +114,9 @@ private:
|
|||
LaunchPhase mLaunchPhase;
|
||||
|
||||
UniquePtr<GPUChild> mGPUChild;
|
||||
Listener* listener_;
|
||||
|
||||
bool mShutdownRequested;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -129,6 +129,14 @@ GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
|
|||
mGPUChild = mProcess->GetActor();
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
|
||||
{
|
||||
MOZ_ASSERT(mProcess && mProcess == aHost);
|
||||
|
||||
DestroyProcess();
|
||||
}
|
||||
|
||||
void
|
||||
GPUProcessManager::DestroyProcess()
|
||||
{
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
dom::TabParent* aBrowserParent);
|
||||
|
||||
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
|
||||
void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
|
||||
|
||||
private:
|
||||
// Called from our xpcom-shutdown observer.
|
||||
|
|
|
@ -10,7 +10,7 @@ sync protocol PGPU
|
|||
{
|
||||
parent:
|
||||
// Sent by the UI process to initiate shutdown.
|
||||
async BeginShutdown();
|
||||
async Nothing();
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
Загрузка…
Ссылка в новой задаче