--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -65,16 +65,34 @@ PR_STATIC_ASSERT(sizeof(NPIdentifier) ==
template<>
struct RunnableMethodTraits<mozilla::plugins::PluginModuleParent>
{
typedef mozilla::plugins::PluginModuleParent Class;
static void RetainCallee(Class* obj) { }
static void ReleaseCallee(Class* obj) { }
};
+class PluginCrashed : public nsRunnable
+{
+public:
+ PluginCrashed(nsNPAPIPlugin* plugin,
+ const nsString& dumpID)
+ : mDumpID(dumpID),
+ mPlugin(plugin) { }
+
+ NS_IMETHOD Run() {
+ mPlugin->PluginCrashed(mDumpID);
+ return NS_OK;
+ }
+
+private:
+ nsNPAPIPlugin* mPlugin;
+ nsString mDumpID;
+};
+
// static
PluginLibrary*
PluginModuleParent::LoadModule(const char* aFilePath)
{
PLUGIN_LOG_DEBUG_FUNCTION;
// Block on the child process being launched and initialized.
PluginModuleParent* parent = new PluginModuleParent(aFilePath);
@@ -89,36 +107,28 @@ PluginModuleParent::LoadModule(const cha
PluginModuleParent::PluginModuleParent(const char* aFilePath)
: mSubprocess(new PluginProcessParent(aFilePath))
, mShutdown(false)
, mNPNIface(NULL)
, mPlugin(NULL)
, mProcessStartTime(time(NULL))
- , mPluginCrashedTask(NULL)
{
NS_ASSERTION(mSubprocess, "Out of memory!");
if (!mValidIdentifiers.Init()) {
NS_ERROR("Out of memory");
}
nsContentUtils::RegisterPrefCallback(kTimeoutPref, TimeoutChanged, this);
}
PluginModuleParent::~PluginModuleParent()
{
- NS_ASSERTION(OkToCleanup(), "unsafe destruction");
-
- if (mPluginCrashedTask) {
- mPluginCrashedTask->Cancel();
- mPluginCrashedTask = 0;
- }
-
if (!mShutdown) {
NS_WARNING("Plugin host deleted the module without shutting down.");
NPError err;
NP_Shutdown(&err);
}
NS_ASSERTION(mShutdown, "NP_Shutdown didn't");
if (mSubprocess) {
@@ -254,64 +264,47 @@ PluginModuleParent::ShouldContinueFromRe
}
void
PluginModuleParent::ActorDestroy(ActorDestroyReason why)
{
switch (why) {
case AbnormalShutdown: {
nsCOMPtr<nsIFile> dump;
+ nsAutoString dumpID;
if (GetMinidump(getter_AddRefs(dump))) {
WriteExtraDataForMinidump(dump);
- if (NS_SUCCEEDED(dump->GetLeafName(mDumpID))) {
- mDumpID.Replace(mDumpID.Length() - 4, 4,
- NS_LITERAL_STRING(""));
+ if (NS_SUCCEEDED(dump->GetLeafName(dumpID))) {
+ dumpID.Replace(dumpID.Length() - 4, 4,
+ NS_LITERAL_STRING(""));
}
}
else {
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
}
mShutdown = true;
// Defer the PluginCrashed method so that we don't re-enter
// and potentially modify the actor child list while enumerating it.
if (mPlugin) {
- mPluginCrashedTask = NewRunnableMethod(
- this, &PluginModuleParent::NotifyPluginCrashed);
- MessageLoop::current()->PostTask(FROM_HERE, mPluginCrashedTask);
+ nsCOMPtr<nsIRunnable> r =
+ new PluginCrashed(mPlugin, dumpID);
+ NS_DispatchToMainThread(r);
}
break;
}
case NormalShutdown:
mShutdown = true;
break;
default:
NS_ERROR("Unexpected shutdown reason for toplevel actor.");
}
}
-void
-PluginModuleParent::NotifyPluginCrashed()
-{
- // MessageLoop owns this
- mPluginCrashedTask = NULL;
-
- if (!OkToCleanup()) {
- // there's still plugin code on the C++ stack. try again
- mPluginCrashedTask = NewRunnableMethod(
- this, &PluginModuleParent::NotifyPluginCrashed);
- MessageLoop::current()->PostTask(FROM_HERE, mPluginCrashedTask);
- return;
- }
-
- if (mPlugin)
- mPlugin->PluginCrashed(mDumpID);
-}
-
PPluginInstanceParent*
PluginModuleParent::AllocPPluginInstance(const nsCString& aMimeType,
const uint16_t& aMode,
const nsTArray<nsCString>& aNames,
const nsTArray<nsCString>& aValues,
NPError* rv)
{
NS_ERROR("Not reachable!");
--- a/dom/plugins/PluginModuleParent.h
+++ b/dom/plugins/PluginModuleParent.h
@@ -115,20 +115,16 @@ public:
const NPNetscapeFuncs* GetNetscapeFuncs() {
return mNPNIface;
}
base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
bool EnsureValidNPIdentifier(NPIdentifier aIdentifier);
- bool OkToCleanup() const {
- return !IsOnCxxStack();
- }
-
protected:
NS_OVERRIDE
virtual mozilla::ipc::RPCChannel::RacyRPCPolicy
MediateRPCRace(const Message& parent, const Message& child)
{
return MediateRace(parent, child);
}
@@ -234,25 +230,22 @@ private:
NPError* error);
private:
void WriteExtraDataForMinidump(nsIFile* dumpFile);
void WriteExtraDataEntry(nsIFileOutputStream* stream,
const char* key,
const char* value);
void CleanupFromTimeout();
static int TimeoutChanged(const char* aPref, void* aModule);
- void NotifyPluginCrashed();
nsCString mCrashNotes;
PluginProcessParent* mSubprocess;
bool mShutdown;
const NPNetscapeFuncs* mNPNIface;
nsTHashtable<nsVoidPtrHashKey> mValidIdentifiers;
nsNPAPIPlugin* mPlugin;
time_t mProcessStartTime;
- CancelableTask* mPluginCrashedTask;
- nsString mDumpID;
};
} // namespace plugins
} // namespace mozilla
#endif // ifndef dom_plugins_PluginModuleParent_h
--- a/ipc/glue/RPCChannel.cpp
+++ b/ipc/glue/RPCChannel.cpp
@@ -176,26 +176,16 @@ RPCChannel::Call(Message* msg, Message*
msg->set_rpc_local_stack_depth(1 + StackDepth());
mStack.push(*msg);
mIOLoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RPCChannel::OnSend, msg));
while (1) {
- // if a handler invoked by *Dispatch*() spun a nested event
- // loop, and the connection was broken during that loop, we
- // might have already processed the OnError event. if so,
- // trying another loop iteration will be futile because
- // channel state will have been cleared
- if (!Connected()) {
- ReportConnectionError("RPCChannel");
- return false;
- }
-
// now might be the time to process a message deferred because
// of race resolution
MaybeProcessDeferredIncall();
// here we're waiting for something to happen. see long
// comment about the queue in RPCChannel.h
while (!EventOccurred()) {
bool maybeTimedOut = !RPCChannel::WaitForNotify();
--- a/ipc/glue/RPCChannel.h
+++ b/ipc/glue/RPCChannel.h
@@ -129,21 +129,16 @@ public:
//
// It is an error to
// - call this on the child side of the channel
// - call this without a matching |BlockChild()|
//
// Return true iff successful.
bool UnblockChild();
- // Return true iff this has code on the C++ stack.
- bool IsOnCxxStack() const {
- return 0 < mCxxStackFrames;
- }
-
NS_OVERRIDE
virtual bool OnSpecialMessage(uint16 id, const Message& msg);
// Override the SyncChannel handler so we can dispatch RPC
// messages. Called on the IO thread only.
NS_OVERRIDE
virtual void OnMessageReceived(const Message& msg);
NS_OVERRIDE
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -1351,20 +1351,16 @@ class Protocol(ipdl.ast.Protocol):
def enteredCxxStackVar(self):
assert self.decl.type.isToplevel()
return ExprVar('EnteredCxxStack')
def exitedCxxStackVar(self):
assert self.decl.type.isToplevel()
return ExprVar('ExitedCxxStack')
- def onCxxStackVar(self):
- assert self.decl.type.isToplevel()
- return ExprVar('IsOnCxxStack')
-
def nextActorIdExpr(self, side):
assert self.decl.type.isToplevel()
if side is 'parent': op = '++'
elif side is 'child': op = '--'
else: assert 0
return ExprPrefixUnop(self.lastActorIdVar(), op)
def actorIdInit(self, side):
@@ -2875,33 +2871,25 @@ class _GenerateProtocolActorCode(ipdl.as
else:
ontimeout.addstmts([
_runtimeAbort("`OnReplyTimeout' called on non-toplevel actor"),
StmtReturn(ExprLiteral.FALSE)
])
self.cls.addstmts([ ontimeout, Whitespace.NL ])
- # C++-stack-related methods
+ # On[Entered/Exited]CxxStack()
if ptype.isToplevel() and toplevel.talksRpc():
- # OnEnteredCxxStack()
onentered = MethodDefn(MethodDecl('OnEnteredCxxStack'))
onentered.addstmt(StmtReturn(ExprCall(p.enteredCxxStackVar())))
- # OnExitedCxxStack()
onexited = MethodDefn(MethodDecl('OnExitedCxxStack'))
onexited.addstmt(StmtReturn(ExprCall(p.exitedCxxStackVar())))
- # bool IsOnCxxStack()
- onstack = MethodDefn(
- MethodDecl(p.onCxxStackVar().name, ret=Type.BOOL, const=1))
- onstack.addstmt(StmtReturn(ExprCall(
- ExprSelect(p.channelVar(), '.', p.onCxxStackVar().name))))
-
- self.cls.addstmts([ onentered, onexited, onstack, Whitespace.NL ])
+ self.cls.addstmts([ onentered, onexited, Whitespace.NL ])
# OnChannelClose()
onclose = MethodDefn(MethodDecl('OnChannelClose'))
if ptype.isToplevel():
onclose.addstmts([
StmtExpr(ExprCall(destroysubtreevar,
args=[ _DestroyReason.NormalShutdown ])),
StmtExpr(ExprCall(deallocsubtreevar))