void PluginModuleParent::ActorDestroy(ActorDestroyReason why) { switch (why) { case AbnormalShutdown: { #ifdef MOZ_CRASHREPORTER CrashReporterParent* crashReporter = CrashReporter(); CrashReporter::AnnotationTable notes; notes.Init(4); WriteExtraDataForMinidump(notes); if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) { crashReporter->GenerateHangCrashReport(¬es); } else if (!mPluginDumpID.IsEmpty()) { // Nothing to do, we've already written this minidump in // PluginModuleParent::OnCrash } else if (crashReporter->GenerateCrashReport(this, ¬es)) { mPluginDumpID = crashReporter->ChildDumpID(); PLUGIN_LOG_DEBUG(("got child minidump: %s", NS_ConvertUTF16toUTF8(mPluginDumpID).get())); } else { NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!"); } #endif 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) MessageLoop::current()->PostTask( FROM_HERE, mTaskFactory.NewRunnableMethod( &PluginModuleParent::NotifyPluginCrashed)); break; } case NormalShutdown: mShutdown = true; break; default: NS_ERROR("Unexpected shutdown reason for toplevel actor."); } }
void ContentParent::ActorDestroy(ActorDestroyReason why) { nsCOMPtr<nsIThreadObserver> kungFuDeathGrip(static_cast<nsIThreadObserver*>(this)); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->RemoveObserver(static_cast<nsIObserver*>(this), "xpcom-shutdown"); obs->RemoveObserver(static_cast<nsIObserver*>(this), "memory-pressure"); obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-memory-reporter-request"); obs->RemoveObserver(static_cast<nsIObserver*>(this), NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC); obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-gc-request"); obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-cc-request"); #ifdef ACCESSIBILITY obs->RemoveObserver(static_cast<nsIObserver*>(this), "a11y-init-or-shutdown"); #endif } mMessageManager->Disconnect(); // clear the child memory reporters InfallibleTArray<MemoryReport> empty; SetChildMemoryReporters(empty); // remove the global remote preferences observers nsCOMPtr<nsIPrefBranch2> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefs) { prefs->RemoveObserver("", this); } RecvRemoveGeolocationListener(); RecvRemoveDeviceMotionListener(); nsCOMPtr<nsIThreadInternal> threadInt(do_QueryInterface(NS_GetCurrentThread())); if (threadInt) threadInt->RemoveObserver(this); if (mRunToCompletionDepth) mRunToCompletionDepth = 0; if (gContentParents) { gContentParents->RemoveElement(this); if (!gContentParents->Length()) { delete gContentParents; gContentParents = NULL; } } mIsAlive = false; if (obs) { nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag(); props->Init(); if (AbnormalShutdown == why) { props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), true); #ifdef MOZ_CRASHREPORTER MOZ_ASSERT(ManagedPCrashReporterParent().Length() > 0); CrashReporterParent* crashReporter = static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]); crashReporter->GenerateCrashReport(this, NULL); nsAutoString dumpID(crashReporter->ChildDumpID()); props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID); #endif obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nsnull); } } MessageLoop::current()-> PostTask(FROM_HERE, NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess)); mSubprocess = NULL; // IPDL rules require actors to live on past ActorDestroy, but it // may be that the kungFuDeathGrip above is the last reference to // |this|. If so, when we go out of scope here, we're deleted and // all hell breaks loose. // // This runnable ensures that a reference to |this| lives on at // least until after the current task finishes running. NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this)); }