зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1085168 - Move timeout on async GMP shutdown to (catch all) non xpcom-shutdown case. r=jesup
This commit is contained in:
Родитель
a4c280a3c0
Коммит
fa856685bf
|
@ -174,6 +174,49 @@ GMPParent::LoadProcess()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
NS_WARNING("Timed out waiting for GMP async shutdown!");
|
||||
GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure);
|
||||
nsRefPtr<GeckoMediaPluginService> service =
|
||||
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||
if (service) {
|
||||
service->AsyncShutdownComplete(parent);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
GMPParent::EnsureAsyncShutdownTimeoutSet()
|
||||
{
|
||||
if (mAsyncShutdownTimeout) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
mAsyncShutdownTimeout = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Set timer to abort waiting for plugin to shutdown if it takes
|
||||
// too long.
|
||||
rv = mAsyncShutdownTimeout->SetTarget(mGMPThread);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
int32_t timeout = GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT;
|
||||
nsRefPtr<GeckoMediaPluginService> service =
|
||||
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||
if (service) {
|
||||
timeout = service->AsyncShutdownTimeoutMs();
|
||||
}
|
||||
return mAsyncShutdownTimeout->InitWithFuncCallback(
|
||||
&AbortWaitingForGMPAsyncShutdown, this, timeout,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
void
|
||||
GMPParent::CloseIfUnused()
|
||||
{
|
||||
|
@ -199,7 +242,8 @@ GMPParent::CloseIfUnused()
|
|||
LOGD(("%s::%s: %p sending async shutdown notification", __CLASS__,
|
||||
__FUNCTION__, this));
|
||||
mAsyncShutdownInProgress = true;
|
||||
if (!SendBeginAsyncShutdown()) {
|
||||
if (!SendBeginAsyncShutdown() ||
|
||||
NS_FAILED(EnsureAsyncShutdownTimeoutSet())) {
|
||||
AbortAsyncShutdown();
|
||||
}
|
||||
}
|
||||
|
@ -219,6 +263,11 @@ GMPParent::AbortAsyncShutdown()
|
|||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
|
||||
|
||||
if (mAsyncShutdownTimeout) {
|
||||
mAsyncShutdownTimeout->Cancel();
|
||||
mAsyncShutdownTimeout = nullptr;
|
||||
}
|
||||
|
||||
if (!mAsyncShutdownRequired || !mAsyncShutdownInProgress) {
|
||||
return;
|
||||
}
|
||||
|
@ -289,6 +338,8 @@ GMPParent::Shutdown()
|
|||
LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
|
||||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
|
||||
MOZ_ASSERT(!mAsyncShutdownTimeout, "Should have canceled shutdown timeout");
|
||||
|
||||
if (mAbnormalShutdownInProgress) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -170,6 +170,8 @@ private:
|
|||
virtual bool RecvAsyncShutdownComplete() MOZ_OVERRIDE;
|
||||
virtual bool RecvAsyncShutdownRequired() MOZ_OVERRIDE;
|
||||
|
||||
nsresult EnsureAsyncShutdownTimeoutSet();
|
||||
|
||||
GMPState mState;
|
||||
nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk
|
||||
nsString mName; // base name of plugin on disk, UTF-16 because used for paths
|
||||
|
@ -188,6 +190,7 @@ private:
|
|||
nsTArray<nsRefPtr<GMPTimerParent>> mTimers;
|
||||
nsTArray<nsRefPtr<GMPStorageParent>> mStorage;
|
||||
nsCOMPtr<nsIThread> mGMPThread;
|
||||
nsCOMPtr<nsITimer> mAsyncShutdownTimeout; // GMP Thread only.
|
||||
// NodeId the plugin is assigned to, or empty if the the plugin is not
|
||||
// assigned to a NodeId.
|
||||
nsAutoCString mNodeId;
|
||||
|
|
|
@ -136,8 +136,8 @@ GeckoMediaPluginService::GetGeckoMediaPluginService()
|
|||
|
||||
NS_IMPL_ISUPPORTS(GeckoMediaPluginService, mozIGeckoMediaPluginService, nsIObserver)
|
||||
|
||||
#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
|
||||
static int32_t sMaxAsyncShutdownWaitMs = 0;
|
||||
static bool sHaveSetTimeoutPrefCache = false;
|
||||
|
||||
GeckoMediaPluginService::GeckoMediaPluginService()
|
||||
: mMutex("GeckoMediaPluginService::mMutex")
|
||||
|
@ -147,9 +147,8 @@ GeckoMediaPluginService::GeckoMediaPluginService()
|
|||
, mWaitingForPluginsAsyncShutdown(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
static bool setTimeoutPrefCache = false;
|
||||
if (!setTimeoutPrefCache) {
|
||||
setTimeoutPrefCache = true;
|
||||
if (!sHaveSetTimeoutPrefCache) {
|
||||
sHaveSetTimeoutPrefCache = true;
|
||||
Preferences::AddIntVarCache(&sMaxAsyncShutdownWaitMs,
|
||||
"media.gmp.async-shutdown-timeout",
|
||||
GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT);
|
||||
|
@ -162,6 +161,13 @@ GeckoMediaPluginService::~GeckoMediaPluginService()
|
|||
MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty());
|
||||
}
|
||||
|
||||
int32_t
|
||||
GeckoMediaPluginService::AsyncShutdownTimeoutMs()
|
||||
{
|
||||
MOZ_ASSERT(sHaveSetTimeoutPrefCache);
|
||||
return sMaxAsyncShutdownWaitMs;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GeckoMediaPluginService::Init()
|
||||
{
|
||||
|
@ -205,16 +211,6 @@ GeckoMediaPluginService::Init()
|
|||
return GetThread(getter_AddRefs(thread));
|
||||
}
|
||||
|
||||
void
|
||||
AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
NS_WARNING("Timed out waiting for GMP async shutdown!");
|
||||
nsRefPtr<GeckoMediaPluginService> service = sSingletonService.get();
|
||||
if (service) {
|
||||
service->AbortAsyncShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
|
@ -533,9 +529,11 @@ GeckoMediaPluginService::AsyncShutdownComplete(GMPParent* aParent)
|
|||
|
||||
mAsyncShutdownPlugins.RemoveElement(aParent);
|
||||
if (mAsyncShutdownPlugins.IsEmpty() && mShuttingDownOnGMPThread) {
|
||||
// The main thread is waiting for async shutdown of plugins,
|
||||
// The main thread may be waiting for async shutdown of plugins,
|
||||
// which has completed. Break the main thread out of its waiting loop.
|
||||
AbortAsyncShutdown();
|
||||
nsRefPtr<nsIRunnable> task(NS_NewRunnableMethod(
|
||||
this, &GeckoMediaPluginService::SetAsyncShutdownComplete));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,47 +544,6 @@ GeckoMediaPluginService::SetAsyncShutdownComplete()
|
|||
mWaitingForPluginsAsyncShutdown = false;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginService::AbortAsyncShutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
for (size_t i = 0; i < mAsyncShutdownPlugins.Length(); i++) {
|
||||
mAsyncShutdownPlugins[i]->AbortAsyncShutdown();
|
||||
}
|
||||
mAsyncShutdownPlugins.Clear();
|
||||
if (mAsyncShutdownTimeout) {
|
||||
mAsyncShutdownTimeout->Cancel();
|
||||
mAsyncShutdownTimeout = nullptr;
|
||||
}
|
||||
nsRefPtr<nsIRunnable> task(NS_NewRunnableMethod(
|
||||
this, &GeckoMediaPluginService::SetAsyncShutdownComplete));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GeckoMediaPluginService::SetAsyncShutdownTimeout()
|
||||
{
|
||||
MOZ_ASSERT(!mAsyncShutdownTimeout);
|
||||
|
||||
nsresult rv;
|
||||
mAsyncShutdownTimeout = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to create timer for async GMP shutdown");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Set timer to abort waiting for plugins to shutdown if they take
|
||||
// too long.
|
||||
rv = mAsyncShutdownTimeout->SetTarget(mGMPThread);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return mAsyncShutdownTimeout->InitWithFuncCallback(
|
||||
&AbortWaitingForGMPAsyncShutdown, nullptr, sMaxAsyncShutdownWaitMs,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginService::UnloadPlugins()
|
||||
{
|
||||
|
@ -607,16 +564,7 @@ GeckoMediaPluginService::UnloadPlugins()
|
|||
mPlugins.Clear();
|
||||
}
|
||||
|
||||
if (!mAsyncShutdownPlugins.IsEmpty()) {
|
||||
// We have plugins that require async shutdown. Set a timer to abort
|
||||
// waiting if they take too long to shutdown.
|
||||
if (NS_FAILED(SetAsyncShutdownTimeout())) {
|
||||
mAsyncShutdownPlugins.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (mAsyncShutdownPlugins.IsEmpty()) {
|
||||
mAsyncShutdownPlugins.Clear();
|
||||
nsRefPtr<nsIRunnable> task(NS_NewRunnableMethod(
|
||||
this, &GeckoMediaPluginService::SetAsyncShutdownComplete));
|
||||
NS_DispatchToMainThread(task);
|
||||
|
|
|
@ -28,6 +28,8 @@ namespace gmp {
|
|||
|
||||
class GMPParent;
|
||||
|
||||
#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
|
||||
|
||||
class GeckoMediaPluginService MOZ_FINAL : public mozIGeckoMediaPluginService
|
||||
, public nsIObserver
|
||||
{
|
||||
|
@ -45,6 +47,8 @@ public:
|
|||
void AsyncShutdownComplete(GMPParent* aParent);
|
||||
void AbortAsyncShutdown();
|
||||
|
||||
int32_t AsyncShutdownTimeoutMs();
|
||||
|
||||
private:
|
||||
~GeckoMediaPluginService();
|
||||
|
||||
|
@ -122,7 +126,6 @@ private:
|
|||
MainThreadOnly<bool> mWaitingForPluginsAsyncShutdown;
|
||||
|
||||
nsTArray<nsRefPtr<GMPParent>> mAsyncShutdownPlugins; // GMP Thread only.
|
||||
nsCOMPtr<nsITimer> mAsyncShutdownTimeout; // GMP Thread only.
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
nsCOMPtr<nsIFile> mStorageBaseDir;
|
||||
|
|
Загрузка…
Ссылка в новой задаче