Bug 1209385 - Crash GMPs that don't respond to GMPVideoDecoder::Reset(). r=jwwang

This commit is contained in:
Chris Pearce 2015-09-30 06:56:07 +13:00
parent 3fd903c9df
commit a76b46867d
15 changed files with 117 additions and 9 deletions

View File

@ -606,10 +606,21 @@ GMPChild::GetGMPStorage()
return mStorage;
}
bool
GMPChild::RecvCrashPluginNow()
static MOZ_NEVER_INLINE void
CrashForApiTimeout()
{
MOZ_CRASH();
// Never inline so that crash reports are distinctive.
MOZ_CRASH("Bug 1209385; GMP API actor failed to respond.");
}
bool
GMPChild::RecvCrashPluginNow(const GMPCrashReason& aReason)
{
if (aReason == kGmpApiTimeout) {
CrashForApiTimeout();
} else {
MOZ_CRASH();
}
return true;
}

View File

@ -71,7 +71,7 @@ private:
ProcessId aOtherPid) override;
void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild);
virtual bool RecvCrashPluginNow() override;
virtual bool RecvCrashPluginNow(const GMPCrashReason& aReason) override;
virtual bool RecvBeginAsyncShutdown() override;
virtual bool RecvCloseActive() override;

View File

@ -118,6 +118,18 @@ GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
CloseIfUnused();
}
void
GMPContentParent::CrashPluginNow(GMPCrashReason aReason)
{
if (mParent) {
mParent->Crash(aReason);
} else {
nsRefPtr<GeckoMediaPluginServiceChild> gmp(
GeckoMediaPluginServiceChild::GetSingleton());
gmp->CrashPluginNow(mPluginId, aReason);
}
}
void
GMPContentParent::CloseIfUnused()
{

View File

@ -9,6 +9,7 @@
#include "mozilla/gmp/PGMPContentParent.h"
#include "GMPSharedMemManager.h"
#include "nsISupportsImpl.h"
#include "GMPUtils.h"
namespace mozilla {
namespace gmp {
@ -61,6 +62,8 @@ public:
return mPluginId;
}
void CrashPluginNow(GMPCrashReason aReason);
private:
~GMPContentParent();

View File

@ -11,6 +11,8 @@
#include "gmp-audio-codec.h"
#include "gmp-decryption.h"
#include "GMPUtils.h"
namespace IPC {
template <>
@ -247,6 +249,13 @@ struct ParamTraits<GMPVideoCodec>
}
};
template <>
struct ParamTraits<mozilla::GMPCrashReason>
: public ContiguousEnumSerializer<mozilla::GMPCrashReason,
mozilla::kPrefChange,
mozilla::kInvalid>
{};
} // namespace IPC
#endif // GMPMessageUtils_h_

View File

@ -119,10 +119,10 @@ GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir)
}
void
GMPParent::Crash()
GMPParent::Crash(GMPCrashReason aReason)
{
if (mState != GMPStateNotLoaded) {
unused << SendCrashPluginNow();
unused << SendCrashPluginNow(aReason);
}
}

View File

@ -22,6 +22,7 @@
#include "nsTArray.h"
#include "nsIFile.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "GMPUtils.h"
class nsIThread;
@ -79,7 +80,7 @@ public:
nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
nsresult CloneFrom(const GMPParent* aOther);
void Crash();
void Crash(GMPCrashReason aReason);
nsresult LoadProcess();

View File

@ -215,6 +215,38 @@ GeckoMediaPluginServiceChild::UpdateTrialCreateState(const nsAString& aKeySystem
return NS_OK;
}
void
GeckoMediaPluginServiceChild::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
{
if (NS_GetCurrentThread() != mGMPThread) {
mGMPThread->Dispatch(NS_NewRunnableMethodWithArgs<uint32_t, GMPCrashReason>(
this, &GeckoMediaPluginServiceChild::CrashPluginNow,
aPluginId, aReason), NS_DISPATCH_NORMAL);
return;
}
class Callback : public GetServiceChildCallback
{
public:
Callback(uint32_t aPluginId, GMPCrashReason aReason)
: mPluginId(aPluginId)
, mReason(aReason)
{ }
virtual void Done(GMPServiceChild* aService) override
{
aService->SendCrashPluginNow(mPluginId, mReason);
}
private:
uint32_t mPluginId;
GMPCrashReason mReason;
};
UniquePtr<GetServiceChildCallback> callback(new Callback(aPluginId, aReason));
GetServiceChild(Move(callback));
}
NS_IMETHODIMP
GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
const char* aTopic,

View File

@ -11,6 +11,7 @@
#include "mozilla/ipc/Transport.h"
#include "mozilla/gmp/PGMPServiceChild.h"
#include "nsRefPtrHashtable.h"
#include "GMPUtils.h"
namespace mozilla {
namespace gmp {
@ -52,6 +53,8 @@ public:
NS_IMETHOD UpdateTrialCreateState(const nsAString& aKeySystem,
uint32_t aState) override;
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
NS_DECL_NSIOBSERVER
void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild);

View File

@ -511,7 +511,7 @@ GeckoMediaPluginServiceParent::CrashPlugins()
MutexAutoLock lock(mMutex);
for (size_t i = 0; i < mPlugins.Length(); i++) {
mPlugins[i]->Crash();
mPlugins[i]->Crash(kPrefChange);
}
}
@ -1221,6 +1221,19 @@ GeckoMediaPluginServiceParent::UpdateTrialCreateState(const nsAString& aKeySyste
#endif
}
void
GeckoMediaPluginServiceParent::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
MutexAutoLock lock(mMutex);
LOGD(("%s::%s(%u, %u)", __CLASS__, __FUNCTION__, aPluginId, aReason));
for (const auto& plugin : mPlugins) {
if (plugin->GetPluginId() == aPluginId) {
plugin->Crash(aReason);
}
}
}
static bool
ExtractHostName(const nsACString& aOrigin, nsACString& aOutData)
{
@ -1555,6 +1568,14 @@ GMPServiceParent::~GMPServiceParent()
new DeleteTask<Transport>(GetTransport()));
}
bool
GMPServiceParent::RecvCrashPluginNow(const uint32_t& aPluginId,
const GMPCrashReason& aReason)
{
mService->CrashPluginNow(aPluginId, aReason);
return true;
}
bool
GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
const nsCString& aAPI,

View File

@ -13,6 +13,7 @@
#include "nsDataHashtable.h"
#include "mozilla/Atomics.h"
#include "nsThreadUtils.h"
#include "GMPUtils.h"
template <class> struct already_AddRefed;
@ -57,6 +58,8 @@ public:
void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState);
#endif // MOZ_CRASHREPORTER
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
private:
friend class GMPServiceParent;
@ -223,6 +226,8 @@ public:
nsCString* aVersion);
virtual bool RecvUpdateGMPTrialCreateState(const nsString& aKeySystem,
const uint32_t& aState) override;
virtual bool RecvCrashPluginNow(const uint32_t& aPluginId,
const GMPCrashReason& aReason) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;

View File

@ -37,6 +37,12 @@ SplitAt(const char* aDelims,
nsCString
ToBase64(const nsTArray<uint8_t>& aBytes);
enum GMPCrashReason {
kPrefChange, // media.gmp.plugin.crash has been toggled.
kGmpApiTimeout, // Some API did not respond.
kInvalid,
};
} // namespace mozilla
#endif

View File

@ -188,6 +188,7 @@ GMPVideoDecoderParent::Reset()
LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get()));
self->mResetCompleteTimeout = nullptr;
LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()"));
self->mPlugin->CrashPluginNow(kGmpApiTimeout);
});
CancelResetCompleteTimeout();
mResetCompleteTimeout = SimpleTimer::Create(task, 5000, mPlugin->GMPThread());

View File

@ -9,6 +9,7 @@ include protocol PGMPTimer;
include protocol PGMPStorage;
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
using mozilla::GMPCrashReason from "GMPUtils.h";
namespace mozilla {
namespace gmp {
@ -33,7 +34,7 @@ parent:
child:
async BeginAsyncShutdown();
async CrashPluginNow();
async CrashPluginNow(GMPCrashReason aReason);
intr StartPlugin();
async SetNodeId(nsCString nodeId);
async CloseActive();

View File

@ -6,6 +6,7 @@
include protocol PGMP;
using base::ProcessId from "base/process.h";
using mozilla::GMPCrashReason from "GMPUtils.h";
namespace mozilla {
namespace gmp {
@ -23,6 +24,8 @@ parent:
returns (nsCString id);
async UpdateGMPTrialCreateState(nsString keySystem, uint32_t status);
async CrashPluginNow(uint32_t pluginId, GMPCrashReason aReason);
};
} // namespace gmp