mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1115438: Move PluginModuleParent's invocation of CreateToolhelp32Snapshot off the main thread; r=jimm
This commit is contained in:
parent
14d009b649
commit
56c951c61f
@ -37,7 +37,6 @@
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "mozilla/widget/AudioSession.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "PluginHangUIParent.h"
|
||||
#endif
|
||||
|
||||
@ -114,6 +113,63 @@ mozilla::plugins::SetupBridge(uint32_t aPluginId,
|
||||
return PPluginModule::Bridge(aContentParent, chromeParent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use for executing CreateToolhelp32Snapshot off main thread
|
||||
*/
|
||||
class mozilla::plugins::FinishInjectorInitTask : public CancelableTask
|
||||
{
|
||||
public:
|
||||
FinishInjectorInitTask()
|
||||
: mMutex("FlashInjectorInitTask::mMutex")
|
||||
, mParent(nullptr)
|
||||
, mMainThreadMsgLoop(MessageLoop::current())
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
void Init(PluginModuleChromeParent* aParent)
|
||||
{
|
||||
MOZ_ASSERT(aParent);
|
||||
mParent = aParent;
|
||||
}
|
||||
|
||||
void PostToMainThread()
|
||||
{
|
||||
mSnapshot.own(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
|
||||
bool deleteThis = false;
|
||||
{ // Scope for lock
|
||||
mozilla::MutexAutoLock lock(mMutex);
|
||||
if (mMainThreadMsgLoop) {
|
||||
mMainThreadMsgLoop->PostTask(FROM_HERE, this);
|
||||
} else {
|
||||
deleteThis = true;
|
||||
}
|
||||
}
|
||||
if (deleteThis) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void Run() MOZ_OVERRIDE
|
||||
{
|
||||
mParent->DoInjection(mSnapshot);
|
||||
}
|
||||
|
||||
void Cancel() MOZ_OVERRIDE
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mMutex);
|
||||
mMainThreadMsgLoop = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
mozilla::Mutex mMutex;
|
||||
nsAutoHandle mSnapshot;
|
||||
PluginModuleChromeParent* mParent;
|
||||
MessageLoop* mMainThreadMsgLoop;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Objects of this class remain linked until either an error occurs in the
|
||||
* plugin initialization sequence, or until
|
||||
@ -264,6 +320,8 @@ PRCList PluginModuleMapping::sModuleListHead =
|
||||
|
||||
bool PluginModuleMapping::sIsLoadModuleOnStack = false;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
mozilla::plugins::TerminatePlugin(uint32_t aPluginId)
|
||||
{
|
||||
@ -586,6 +644,7 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
, mFlashProcess1(0)
|
||||
, mFlashProcess2(0)
|
||||
, mFinishInitTask(nullptr)
|
||||
#endif
|
||||
, mInitOnAsyncConnect(false)
|
||||
, mAsyncInitRv(NS_ERROR_NOT_INITIALIZED)
|
||||
@ -633,6 +692,10 @@ PluginModuleChromeParent::~PluginModuleChromeParent()
|
||||
UnregisterInjectorCallback(mFlashProcess1);
|
||||
if (mFlashProcess2)
|
||||
UnregisterInjectorCallback(mFlashProcess2);
|
||||
if (mFinishInitTask) {
|
||||
// mFinishInitTask will be deleted by the main thread message_loop
|
||||
mFinishInitTask->Cancel();
|
||||
}
|
||||
#endif
|
||||
|
||||
UnregisterSettingsCallbacks();
|
||||
@ -2606,22 +2669,41 @@ PluginModuleChromeParent::InitializeInjector()
|
||||
return;
|
||||
|
||||
TimeStamp th32Start = TimeStamp::Now();
|
||||
nsAutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
|
||||
if (INVALID_HANDLE_VALUE == snapshot)
|
||||
mFinishInitTask = mChromeTaskFactory.NewTask<FinishInjectorInitTask>();
|
||||
mFinishInitTask->Init(this);
|
||||
if (!::QueueUserWorkItem(&PluginModuleChromeParent::GetToolhelpSnapshot,
|
||||
mFinishInitTask, WT_EXECUTEDEFAULT)) {
|
||||
delete mFinishInitTask;
|
||||
mFinishInitTask = nullptr;
|
||||
return;
|
||||
}
|
||||
TimeStamp th32End = TimeStamp::Now();
|
||||
mTimeBlocked += (th32End - th32Start);
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChromeParent::DoInjection(const nsAutoHandle& aSnapshot)
|
||||
{
|
||||
DWORD pluginProcessPID = GetProcessId(Process()->GetChildProcessHandle());
|
||||
mFlashProcess1 = GetFlashChildOfPID(pluginProcessPID, snapshot);
|
||||
mFlashProcess1 = GetFlashChildOfPID(pluginProcessPID, aSnapshot);
|
||||
if (mFlashProcess1) {
|
||||
InjectCrashReporterIntoProcess(mFlashProcess1, this);
|
||||
|
||||
mFlashProcess2 = GetFlashChildOfPID(mFlashProcess1, snapshot);
|
||||
mFlashProcess2 = GetFlashChildOfPID(mFlashProcess1, aSnapshot);
|
||||
if (mFlashProcess2) {
|
||||
InjectCrashReporterIntoProcess(mFlashProcess2, this);
|
||||
}
|
||||
}
|
||||
mFinishInitTask = nullptr;
|
||||
}
|
||||
|
||||
DWORD WINAPI
|
||||
PluginModuleChromeParent::GetToolhelpSnapshot(LPVOID aContext)
|
||||
{
|
||||
FinishInjectorInitTask* task = static_cast<FinishInjectorInitTask*>(aContext);
|
||||
MOZ_ASSERT(task);
|
||||
task->PostToMainThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -11,11 +11,11 @@
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "mozilla/HangMonitor.h"
|
||||
#include "mozilla/PluginLibrary.h"
|
||||
#include "mozilla/plugins/ScopedMethodFactory.h"
|
||||
#include "mozilla/plugins/PluginProcessParent.h"
|
||||
#include "mozilla/plugins/PPluginModuleParent.h"
|
||||
#include "mozilla/plugins/PluginMessageUtils.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
#include "mozilla/plugins/TaskFactory.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "npapi.h"
|
||||
#include "npfunctions.h"
|
||||
@ -23,6 +23,9 @@
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIObserver.h"
|
||||
#ifdef XP_WIN
|
||||
#include "nsWindowsHelpers.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsExceptionHandler.h"
|
||||
@ -46,6 +49,9 @@ class PluginInstanceParent;
|
||||
#ifdef XP_WIN
|
||||
class PluginHangUIParent;
|
||||
#endif
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
class FinishInjectorInitTask;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PluginModuleParent
|
||||
@ -273,7 +279,7 @@ protected:
|
||||
NPNetscapeFuncs* mNPNIface;
|
||||
NPPluginFuncs* mNPPIface;
|
||||
nsNPAPIPlugin* mPlugin;
|
||||
ScopedMethodFactory<PluginModuleParent> mTaskFactory;
|
||||
TaskFactory<PluginModuleParent> mTaskFactory;
|
||||
nsString mPluginDumpID;
|
||||
nsString mBrowserDumpID;
|
||||
nsString mHangID;
|
||||
@ -445,7 +451,7 @@ private:
|
||||
PluginProcessParent* mSubprocess;
|
||||
uint32_t mPluginId;
|
||||
|
||||
ScopedMethodFactory<PluginModuleChromeParent> mChromeTaskFactory;
|
||||
TaskFactory<PluginModuleChromeParent> mChromeTaskFactory;
|
||||
|
||||
enum HangAnnotationFlags
|
||||
{
|
||||
@ -493,12 +499,17 @@ private:
|
||||
friend class mozilla::plugins::PluginAsyncSurrogate;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
friend class mozilla::plugins::FinishInjectorInitTask;
|
||||
|
||||
void InitializeInjector();
|
||||
void DoInjection(const nsAutoHandle& aSnapshot);
|
||||
static DWORD WINAPI GetToolhelpSnapshot(LPVOID aContext);
|
||||
|
||||
void OnCrash(DWORD processID) MOZ_OVERRIDE;
|
||||
|
||||
DWORD mFlashProcess1;
|
||||
DWORD mFlashProcess2;
|
||||
mozilla::plugins::FinishInjectorInitTask* mFinishInitTask;
|
||||
#endif
|
||||
|
||||
void OnProcessLaunched(const bool aSucceeded);
|
||||
|
@ -2,23 +2,25 @@
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_plugins_ScopedMethodFactory_h
|
||||
#define mozilla_plugins_ScopedMethodFactory_h
|
||||
#ifndef mozilla_plugins_TaskFactory_h
|
||||
#define mozilla_plugins_TaskFactory_h
|
||||
|
||||
#include <base/task.h>
|
||||
|
||||
/*
|
||||
* This is based on the ScopedRunnableMethodFactory from ipc/chromium/src/base/task.h
|
||||
* Chromiums factories assert if tasks are created and run on different threads,
|
||||
* Chromium's factories assert if tasks are created and run on different threads,
|
||||
* which is something we need to do in PluginModuleParent (hang UI vs. main thread).
|
||||
* ScopedMethodFactory just provides cancellable tasks that don't assert this.
|
||||
* TaskFactory just provides cancellable tasks that don't assert this.
|
||||
* This version also allows both ScopedMethod and regular Tasks to be generated
|
||||
* by the same Factory object.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
template<class T>
|
||||
class ScopedMethodFactory : public RevocableStore
|
||||
class TaskFactory : public RevocableStore
|
||||
{
|
||||
private:
|
||||
template<class TaskType>
|
||||
@ -37,7 +39,15 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
explicit ScopedMethodFactory(T* object) : object_(object) { }
|
||||
explicit TaskFactory(T* object) : object_(object) { }
|
||||
|
||||
template <class TaskParamType>
|
||||
inline TaskParamType* NewTask()
|
||||
{
|
||||
typedef TaskWrapper<TaskParamType> TaskWrapper;
|
||||
TaskWrapper* task = new TaskWrapper(this);
|
||||
return task;
|
||||
}
|
||||
|
||||
template <class Method>
|
||||
inline Task* NewRunnableMethod(Method method) {
|
||||
@ -84,4 +94,4 @@ private:
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_ScopedMethodFactory_h
|
||||
#endif // mozilla_plugins_TaskFactory_h
|
@ -40,9 +40,9 @@ EXPORTS.mozilla.plugins += [
|
||||
'PluginUtilsOSX.h',
|
||||
'PluginWidgetChild.h',
|
||||
'PluginWidgetParent.h',
|
||||
'ScopedMethodFactory.h',
|
||||
'StreamNotifyChild.h',
|
||||
'StreamNotifyParent.h',
|
||||
'TaskFactory.h',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
|
Loading…
Reference in New Issue
Block a user