author | Josh Matthews <josh@joshmatthews.net> |
Wed, 29 Jun 2011 23:44:28 -0400 | |
changeset 72771 | 6b0220948f386926493ab977ab0fb7f5708710e7 |
parent 72733 | ec1c5047fa39892340f2e352511e228f8a7d5986 |
child 72772 | bbb6d83ac28c35327e256bedb5a9129ff4a51a76 |
push id | 45 |
push user | ffxbld |
push date | Thu, 22 Sep 2011 17:29:26 +0000 |
treeherder | mozilla-release@b3273da80b44 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 581341 |
milestone | 7.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -255,19 +255,18 @@ ContentChild::Init(MessageLoop* aIOLoop, XRE_InstallX11ErrorHandler(); #endif NS_ASSERTION(!sSingleton, "only one ContentChild per child"); Open(aChannel, aParentHandle, aIOLoop); sSingleton = this; - CrashReporterChild::CreateCrashReporter(this); #if defined(ANDROID) && defined(MOZ_CRASHREPORTER) - PCrashReporterChild* crashreporter = ManagedPCrashReporterChild()[0]; + PCrashReporterChild* crashreporter = SendPCrashReporterConstructor(); InfallibleTArray<Mapping> mappings; const struct mapping_info *info = getLibraryMapping(); while (info && info->name) { mappings.AppendElement(Mapping(nsDependentCString(info->name), nsDependentCString(info->file_id), info->base, info->len, info->offset)); @@ -359,24 +358,19 @@ bool ContentChild::DeallocPBrowser(PBrowserChild* iframe) { TabChild* child = static_cast<TabChild*>(iframe); NS_RELEASE(child); return true; } PCrashReporterChild* -ContentChild::AllocPCrashReporter(const NativeThreadId& tid, - const PRUint32& processType) +ContentChild::AllocPCrashReporter() { -#ifdef MOZ_CRASHREPORTER return new CrashReporterChild(); -#else - return nsnull; -#endif } bool ContentChild::DeallocPCrashReporter(PCrashReporterChild* crashreporter) { delete crashreporter; return true; }
--- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -75,21 +75,18 @@ public: } /* if you remove this, please talk to cjones or dougt */ virtual bool RecvDummy(Shmem& foo) { return true; } virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags); virtual bool DeallocPBrowser(PBrowserChild*); - virtual PCrashReporterChild* - AllocPCrashReporter(const NativeThreadId& id, - const PRUint32& processType); - virtual bool - DeallocPCrashReporter(PCrashReporterChild*); + virtual PCrashReporterChild* AllocPCrashReporter(); + virtual bool DeallocPCrashReporter(PCrashReporterChild*); virtual PMemoryReportRequestChild* AllocPMemoryReportRequest(); virtual bool DeallocPMemoryReportRequest(PMemoryReportRequestChild* actor); virtual bool
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -285,23 +285,37 @@ ContentParent::ActorDestroy(ActorDestroy if (obs) { nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag(); props->Init(); if (AbnormalShutdown == why) { props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), PR_TRUE); #ifdef MOZ_CRASHREPORTER - CrashReporterParent* crashReporter = - static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]); + nsAutoString dumpID; + + nsCOMPtr<nsILocalFile> crashDump; + TakeMinidump(getter_AddRefs(crashDump)) && + CrashReporter::GetIDFromMinidump(crashDump, dumpID); + + props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID); - crashReporter->GenerateCrashReport(this, NULL); + if (!dumpID.IsEmpty()) { + CrashReporter::AnnotationTable notes; + notes.Init(); + notes.Put(NS_LITERAL_CSTRING("ProcessType"), NS_LITERAL_CSTRING("content")); - nsAutoString dumpID(crashReporter->ChildDumpID()); - props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID); + char startTime[32]; + sprintf(startTime, "%lld", static_cast<PRInt64>(mProcessStartTime)); + notes.Put(NS_LITERAL_CSTRING("StartupTime"), + nsDependentCString(startTime)); + + // TODO: Additional per-process annotations. + CrashReporter::AppendExtraData(dumpID, notes); + } #endif obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nsnull); } } MessageLoop::current()-> PostTask(FROM_HERE, @@ -322,29 +336,22 @@ ContentParent::CreateTestShell() } bool ContentParent::DestroyTestShell(TestShellParent* aTestShell) { return PTestShellParent::Send__delete__(aTestShell); } -TestShellParent* -ContentParent::GetTestShellSingleton() -{ - if (!ManagedPTestShellParent().Length()) - return nsnull; - return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]); -} - ContentParent::ContentParent() : mGeolocationWatchID(-1) , mRunToCompletionDepth(0) , mShouldCallUnblockChild(false) , mIsAlive(true) + , mProcessStartTime(time(NULL)) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content); mSubprocess->AsyncLaunch(); Open(mSubprocess->GetChannel(), mSubprocess->GetChildProcessHandle()); nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService(); nsChromeRegistryChrome* chromeRegistry = @@ -667,24 +674,19 @@ bool ContentParent::DeallocPBrowser(PBrowserParent* frame) { TabParent* parent = static_cast<TabParent*>(frame); NS_RELEASE(parent); return true; } PCrashReporterParent* -ContentParent::AllocPCrashReporter(const NativeThreadId& tid, - const PRUint32& processType) +ContentParent::AllocPCrashReporter() { -#ifdef MOZ_CRASHREPORTER - return new CrashReporterParent(tid, processType); -#else - return nsnull; -#endif + return new CrashReporterParent(); } bool ContentParent::DeallocPCrashReporter(PCrashReporterParent* crashreporter) { delete crashreporter; return true; }
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -89,29 +89,24 @@ public: NS_DECL_NSITHREADOBSERVER NS_DECL_NSIDOMGEOPOSITIONCALLBACK NS_DECL_NSIDEVICEMOTIONLISTENER TabParent* CreateTab(PRUint32 aChromeFlags); TestShellParent* CreateTestShell(); bool DestroyTestShell(TestShellParent* aTestShell); - TestShellParent* GetTestShellSingleton(); void ReportChildAlreadyBlocked(); bool RequestRunToCompletion(); bool IsAlive(); void SetChildMemoryReporters(const InfallibleTArray<MemoryReport>& report); - GeckoChildProcessHost* Process() { - return mSubprocess; - } - protected: void OnChannelConnected(int32 pid); virtual void ActorDestroy(ActorDestroyReason why); private: static ContentParent* gSingleton; // Hide the raw constructor methods since we don't want client code @@ -122,18 +117,17 @@ private: ContentParent(); virtual ~ContentParent(); void Init(); virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags); virtual bool DeallocPBrowser(PBrowserParent* frame); - virtual PCrashReporterParent* AllocPCrashReporter(const NativeThreadId& tid, - const PRUint32& processType); + virtual PCrashReporterParent* AllocPCrashReporter(); virtual bool DeallocPCrashReporter(PCrashReporterParent* crashreporter); virtual PMemoryReportRequestParent* AllocPMemoryReportRequest(); virtual bool DeallocPMemoryReportRequest(PMemoryReportRequestParent* actor); virtual PTestShellParent* AllocPTestShell(); virtual bool DeallocPTestShell(PTestShellParent* shell); @@ -229,16 +223,15 @@ private: // This is a cache of all of the memory reporters // registered in the child process. To update this, one // can broadcast the topic "child-memory-reporter-request" using // the nsIObserverService. nsCOMArray<nsIMemoryReporter> mMemoryReporters; bool mIsAlive; nsCOMPtr<nsIPrefServiceInternal> mPrefService; - - friend class CrashReporterParent; + time_t mProcessStartTime; }; } // namespace dom } // namespace mozilla #endif
deleted file mode 100644 --- a/dom/ipc/CrashReporterChild.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set sw=4 ts=8 et tw=80 : - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Crash Reporter. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Josh Matthews <josh@joshmatthews.net> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "mozilla/plugins/PluginModuleChild.h" -#include "ContentChild.h" -#include "CrashReporterChild.h" -#include "nsXULAppAPI.h" - -using mozilla::plugins::PluginModuleChild; - -namespace mozilla { -namespace dom { - -/*static*/ -PCrashReporterChild* -CrashReporterChild::GetCrashReporter() -{ - switch (XRE_GetProcessType()) { - case GeckoProcessType_Content: { - ContentChild* child = ContentChild::GetSingleton(); - return child->ManagedPCrashReporterChild()[0]; - } - case GeckoProcessType_Plugin: { - PluginModuleChild* child = PluginModuleChild::current(); - return child->ManagedPCrashReporterChild()[0]; - } - default: - return nsnull; - } -} - -} -}
--- a/dom/ipc/CrashReporterChild.h +++ b/dom/ipc/CrashReporterChild.h @@ -32,41 +32,24 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "mozilla/dom/PCrashReporterChild.h" -#include "mozilla/Util.h" -#ifdef MOZ_CRASHREPORTER -#include "nsExceptionHandler.h" -#include "nsXULAppAPI.h" -#endif namespace mozilla { namespace dom { class CrashReporterChild : public PCrashReporterChild { public: CrashReporterChild() { - MOZ_COUNT_CTOR(CrashReporterChild); - } - ~CrashReporterChild() { - MOZ_COUNT_DTOR(CrashReporterChild); + MOZ_COUNT_CTOR(CrashReporterChild); } - - static PCrashReporterChild* GetCrashReporter(); - - template<class Toplevel> - static void CreateCrashReporter(Toplevel* actor) { -#ifdef MOZ_CRASHREPORTER - MOZ_ASSERT(actor->ManagedPCrashReporterChild().Length() == 0); - actor->SendPCrashReporterConstructor( - CrashReporter::CurrentThreadId(), - XRE_GetProcessType()); -#endif + virtual ~CrashReporterChild() { + MOZ_COUNT_DTOR(CrashReporterChild); } }; } // namespace dom } // namespace mozilla
--- a/dom/ipc/CrashReporterParent.cpp +++ b/dom/ipc/CrashReporterParent.cpp @@ -32,21 +32,22 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "CrashReporterParent.h" +#if defined(MOZ_CRASHREPORTER) +#include "nsExceptionHandler.h" +#endif #include "base/process_util.h" -#include <time.h> - using namespace base; namespace mozilla { namespace dom { void CrashReporterParent::ActorDestroy(ActorDestroyReason why) { @@ -67,96 +68,20 @@ CrashReporterParent::RecvAddLibraryMappi m.start_address(), m.mapping_length(), m.file_offset()); } #endif return true; } -bool -CrashReporterParent::RecvAnnotateCrashReport(const nsCString& key, - const nsCString& data) -{ -#ifdef MOZ_CRASHREPORTER - mNotes.Put(key, data); -#endif - return true; -} - -bool -CrashReporterParent::RecvAppendAppNotes(const nsCString& data) -{ - mAppNotes.Append(data); - return true; -} - -CrashReporterParent::CrashReporterParent(const NativeThreadId& tid, - const PRUint32& processType) -: mMainThread(tid) -, mStartTime(time(NULL)) -, mProcessType(processType) +CrashReporterParent::CrashReporterParent() { MOZ_COUNT_CTOR(CrashReporterParent); - -#ifdef MOZ_CRASHREPORTER - mNotes.Init(4); -#endif } CrashReporterParent::~CrashReporterParent() { MOZ_COUNT_DTOR(CrashReporterParent); } -#ifdef MOZ_CRASHREPORTER -bool -CrashReporterParent::GenerateHangCrashReport(const AnnotationTable* processNotes) -{ - if (mChildDumpID.IsEmpty()) - return false; - - GenerateChildData(processNotes); - - CrashReporter::AnnotationTable notes; - if (!notes.Init(4)) - return false; - notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID)); - if (!CrashReporter::AppendExtraData(mParentDumpID, notes)) - NS_WARNING("problem appending parent data to .extra"); - return true; -} - -bool -CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes) -{ - nsCAutoString type; - switch (mProcessType) { - case GeckoProcessType_Content: - type = NS_LITERAL_CSTRING("content"); - break; - case GeckoProcessType_Plugin: - type = NS_LITERAL_CSTRING("plugin"); - break; - default: - NS_ERROR("unknown process type"); - break; - } - mNotes.Put(NS_LITERAL_CSTRING("ProcessType"), type); - - char startTime[32]; - sprintf(startTime, "%lld", static_cast<PRInt64>(mStartTime)); - mNotes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime)); - - if (!mAppNotes.IsEmpty()) - mNotes.Put(NS_LITERAL_CSTRING("Notes"), mAppNotes); - - bool ret = CrashReporter::AppendExtraData(mChildDumpID, mNotes); - if (ret && processNotes) - ret = CrashReporter::AppendExtraData(mChildDumpID, *processNotes); - if (!ret) - NS_WARNING("problem appending child data to .extra"); - return ret; -} -#endif - } // namespace dom } // namespace mozilla
--- a/dom/ipc/CrashReporterParent.h +++ b/dom/ipc/CrashReporterParent.h @@ -1,9 +1,9 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set sw=4 ts=8 et tw=80 : * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ @@ -32,139 +32,26 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "mozilla/dom/PCrashReporterParent.h" -#include "mozilla/dom/TabMessageUtils.h" -#include "nsXULAppAPI.h" -#include "nsILocalFile.h" -#ifdef MOZ_CRASHREPORTER -#include "nsExceptionHandler.h" -#endif namespace mozilla { namespace dom { -class ProcessReporter; - class CrashReporterParent : public PCrashReporterParent { -#ifdef MOZ_CRASHREPORTER - typedef CrashReporter::AnnotationTable AnnotationTable; -#endif public: - CrashReporterParent(const NativeThreadId& tid, const PRUint32& processType); - virtual ~CrashReporterParent(); - -#ifdef MOZ_CRASHREPORTER - /* Attempt to generate a parent/child pair of minidumps from the given - toplevel actor in the event of a hang. Returns true if successful, - false otherwise. - */ - template<class Toplevel> - bool - GeneratePairedMinidump(Toplevel* t); - - /* Attempt to create a bare-bones crash report for a hang, along with extra - process-specific annotations present in the given AnnotationTable. Returns - true if successful, false otherwise. - */ - bool - GenerateHangCrashReport(const AnnotationTable* processNotes); - - /* Attempt to create a bare-bones crash report, along with extra process- - specific annotations present in the given AnnotationTable. Returns true if - successful, false otherwise. - */ - template<class Toplevel> - bool - GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes); -#endif - - /* Returns the shared hang ID of a parent/child paired minidump. - GeneratePairedMinidump must be called first. - */ - const nsString& HangID() { - return mHangID; - } - /* Returns the ID of the parent minidump. - GeneratePairedMinidump must be called first. - */ - const nsString& ParentDumpID() { - return mParentDumpID; - } - /* Returns the ID of the child minidump. - GeneratePairedMinidump or GenerateCrashReport must be called first. - */ - const nsString& ChildDumpID() { - return mChildDumpID; - } + CrashReporterParent(); + virtual ~CrashReporterParent(); protected: virtual void ActorDestroy(ActorDestroyReason why); virtual bool RecvAddLibraryMappings(const InfallibleTArray<Mapping>& m); - virtual bool - RecvAnnotateCrashReport(const nsCString& key, const nsCString& data); - virtual bool - RecvAppendAppNotes(const nsCString& data); - -#ifdef MOZ_CRASHREPORTER - bool - GenerateChildData(const AnnotationTable* processNotes); - - CrashReporter::AnnotationTable mNotes; -#endif - nsCString mAppNotes; - nsString mHangID; - nsString mChildDumpID; - nsString mParentDumpID; - NativeThreadId mMainThread; - time_t mStartTime; - PRUint32 mProcessType; }; - -#ifdef MOZ_CRASHREPORTER -template<class Toplevel> -inline bool -CrashReporterParent::GeneratePairedMinidump(Toplevel* t) -{ - CrashReporter::ProcessHandle child; -#ifdef XP_MACOSX - child = t->Process()->GetChildTask(); -#else - child = t->OtherProcess(); -#endif - nsCOMPtr<nsILocalFile> childDump; - nsCOMPtr<nsILocalFile> parentDump; - if (CrashReporter::CreatePairedMinidumps(child, - mMainThread, - &mHangID, - getter_AddRefs(childDump), - getter_AddRefs(parentDump)) && - CrashReporter::GetIDFromMinidump(childDump, mChildDumpID) && - CrashReporter::GetIDFromMinidump(parentDump, mParentDumpID)) { - return true; - } - return false; -} - -template<class Toplevel> -inline bool -CrashReporterParent::GenerateCrashReport(Toplevel* t, - const AnnotationTable* processNotes) -{ - nsCOMPtr<nsILocalFile> crashDump; - if (t->TakeMinidump(getter_AddRefs(crashDump)) && - CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) { - return GenerateChildData(processNotes); - } - return false; -} -#endif - } // namespace dom } // namespace mozilla
--- a/dom/ipc/Makefile.in +++ b/dom/ipc/Makefile.in @@ -58,41 +58,40 @@ EXPORTS_NAMESPACES = mozilla/dom EXPORTS_mozilla/dom = \ ContentChild.h \ ContentParent.h \ ContentProcess.h \ CrashReporterChild.h \ CrashReporterParent.h \ TabParent.h \ TabChild.h \ - TabMessageUtils.h \ $(NULL) CPPSRCS = \ ContentProcess.cpp \ ContentParent.cpp \ ContentChild.cpp \ CrashReporterParent.cpp \ - CrashReporterChild.cpp \ TabParent.cpp \ TabChild.cpp \ TabMessageUtils.cpp \ $(NULL) ifdef MOZ_SYDNEYAUDIO EXPORTS_mozilla/dom += \ AudioChild.h \ AudioParent.h \ $(NULL) CPPSRCS += \ AudioChild.cpp \ AudioParent.cpp \ $(NULL) endif + include $(topsrcdir)/config/config.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ -I$(srcdir)/../../content/base/src \ -I$(srcdir)/../../content/events/src \ -I$(srcdir)/../../toolkit/components/places \
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -42,31 +42,29 @@ include protocol PCrashReporter; include protocol PTestShell; include protocol PNecko; include protocol PExternalHelperApp; include protocol PStorage; include protocol PMemoryReportRequest; include "mozilla/chrome/RegistryMessageUtils.h"; include "mozilla/net/NeckoMessageUtils.h"; -include "mozilla/dom/TabMessageUtils.h"; include "nsGeoPositionIPCSerialiser.h"; include "PPrefTuple.h"; using GeoPosition; using PrefTuple; using ChromePackage; using ResourceMapping; using OverrideMapping; using IPC::URI; using IPC::Permission; using mozilla::null_t; -using mozilla::dom::NativeThreadId; using gfxIntSize; namespace mozilla { namespace dom { // Data required to clone an existing DOMStorageImpl in the parent struct StorageClone { @@ -128,17 +126,17 @@ child: DeviceMotionChanged(long type, double x, double y, double z); ScreenSizeChanged(gfxIntSize size); FlushMemory(nsString reason); parent: PNecko(); - PCrashReporter(NativeThreadId tid, PRUint32 processType); + PCrashReporter(); PStorage(StorageConstructData data); PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat); // Services remoting async StartVisitedQuery(URI uri);
--- a/dom/ipc/PCrashReporter.ipdl +++ b/dom/ipc/PCrashReporter.ipdl @@ -33,32 +33,29 @@ * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ include protocol PContent; -include protocol PPluginModule; namespace mozilla { namespace dom { struct Mapping { nsCString library_name; nsCString file_id; uintptr_t start_address; size_t mapping_length; size_t file_offset; }; protocol PCrashReporter { - manager PContent or PPluginModule; + manager PContent; parent: AddLibraryMappings(Mapping[] m); - AnnotateCrashReport(nsCString key, nsCString data); - AppendAppNotes(nsCString data); __delete__(); }; } -} +} \ No newline at end of file
--- a/dom/ipc/TabMessageUtils.h +++ b/dom/ipc/TabMessageUtils.h @@ -38,37 +38,26 @@ #ifndef TABMESSAGE_UTILS_H #define TABMESSAGE_UTILS_H #include "IPC/IPCMessageUtils.h" #include "nsIPrivateDOMEvent.h" #include "nsCOMPtr.h" -#ifdef MOZ_CRASHREPORTER -#include "nsExceptionHandler.h" -#endif - namespace mozilla { namespace dom { struct RemoteDOMEvent { nsCOMPtr<nsIPrivateDOMEvent> mEvent; }; bool ReadRemoteEvent(const IPC::Message* aMsg, void** aIter, mozilla::dom::RemoteDOMEvent* aResult); -#ifdef MOZ_CRASHREPORTER -typedef CrashReporter::ThreadId NativeThreadId; -#else -// unused in this case -typedef int32 NativeThreadId; -#endif - } } namespace IPC { template<> struct ParamTraits<mozilla::dom::RemoteDOMEvent> { @@ -84,12 +73,13 @@ struct ParamTraits<mozilla::dom::RemoteD return mozilla::dom::ReadRemoteEvent(aMsg, aIter, aResult); } static void Log(const paramType& aParam, std::wstring* aLog) { } }; + } #endif
--- a/dom/plugins/ipc/PPluginModule.ipdl +++ b/dom/plugins/ipc/PPluginModule.ipdl @@ -34,37 +34,34 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ include protocol PPluginIdentifier; include protocol PPluginInstance; -include protocol PCrashReporter; include "npapi.h"; include "mozilla/plugins/PluginMessageUtils.h"; -include "mozilla/dom/TabMessageUtils.h"; using NPError; using NPNVariable; using base::FileDescriptor; -using mozilla::dom::NativeThreadId; +using mozilla::plugins::NativeThreadId; using mac_plugin_interposing::NSCursorInfo; using nsID; namespace mozilla { namespace plugins { rpc protocol PPluginModule { manages PPluginInstance; manages PPluginIdentifier; - manages PCrashReporter; both: /** * Sending a void string to this constructor creates an int identifier whereas * sending a non-void string will create a string identifier. This constructor * may be called by either child or parent. If a race occurs by calling the * constructor with the same string or int argument then we create two actors * and detect the second instance in the child. We prevent the parent's actor @@ -83,17 +80,17 @@ both: child: // Forces the child process to update its plugin function table. rpc NP_GetEntryPoints() returns (NPError rv); // Return the plugin's thread ID, if it can be found. rpc NP_Initialize() - returns (NPError rv); + returns (NativeThreadId tid, NPError rv); rpc PPluginInstance(nsCString aMimeType, uint16_t aMode, nsCString[] aNames, nsCString[] aValues) returns (NPError rv); rpc NP_Shutdown() @@ -136,25 +133,25 @@ parent: bool aBoolVal); // Wake up and process a few native events. Periodically called by // Gtk-specific code upon detecting that the plugin process has // entered a nested event loop. If the browser doesn't process // native events, then "livelock" and some other glitches can occur. rpc ProcessSomeEvents(); + sync AppendNotesToCrashReport(nsCString aNotes); + // OS X Specific calls to manage the plugin's window // when interposing system calls. async PluginShowWindow(uint32_t aWindowId, bool aModal, int32_t aX, int32_t aY, size_t aWidth, size_t aHeight); async PluginHideWindow(uint32_t aWindowId); - async PCrashReporter(NativeThreadId tid, PRUint32 processType); - // OS X Specific calls to allow the plugin to manage the cursor. async SetCursor(NSCursorInfo cursorInfo); async ShowCursor(bool show); async PushCursor(NSCursorInfo cursorInfo); async PopCursor(); sync GetNativeCursorsSupported() returns (bool supported); };
--- a/dom/plugins/ipc/PluginMessageUtils.h +++ b/dom/plugins/ipc/PluginMessageUtils.h @@ -137,16 +137,23 @@ typedef intptr_t NativeWindowHandle; // #endif #ifdef XP_WIN typedef base::SharedMemoryHandle WindowsSharedMemoryHandle; #else typedef mozilla::null_t WindowsSharedMemoryHandle; #endif +#ifdef MOZ_CRASHREPORTER +typedef CrashReporter::ThreadId NativeThreadId; +#else +// unused in this case +typedef int32 NativeThreadId; +#endif + // XXX maybe not the best place for these. better one? #define VARSTR(v_) case v_: return #v_ inline const char* const NPPVariableToString(NPPVariable aVar) { switch (aVar) { VARSTR(NPPVpluginNameString);
--- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -60,34 +60,31 @@ #ifdef MOZ_X11 # include "mozilla/X11Util.h" #endif #include "mozilla/plugins/PluginInstanceChild.h" #include "mozilla/plugins/StreamNotifyChild.h" #include "mozilla/plugins/BrowserStreamChild.h" #include "mozilla/plugins/PluginStreamChild.h" #include "PluginIdentifierChild.h" -#include "mozilla/dom/CrashReporterChild.h" #include "nsNPAPIPlugin.h" #ifdef XP_WIN #include "COMMessageFilter.h" #include "nsWindowsDllInterceptor.h" #include "mozilla/widget/AudioSession.h" #endif #ifdef MOZ_WIDGET_COCOA #include "PluginInterposeOSX.h" #include "PluginUtilsOSX.h" #endif using namespace mozilla::plugins; -using mozilla::dom::CrashReporterChild; -using mozilla::dom::PCrashReporterChild; #if defined(XP_WIN) const PRUnichar * kFlashFullscreenClass = L"ShockwaveFlashFullScreen"; const PRUnichar * kMozillaWindowClass = L"MozillaWindowClass"; #endif namespace { PluginModuleChild* gInstance = nsnull; @@ -261,17 +258,16 @@ PluginModuleChild::Init(const std::strin #ifdef XP_MACOSX nsPluginInfo info = nsPluginInfo(); rv = pluginFile.GetPluginInfo(info, &mLibrary); if (rv == NS_OK) { mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName); } #endif - CrashReporterChild::CreateCrashReporter(this); return true; } #if defined(MOZ_WIDGET_GTK2) typedef void (*GObjectDisposeFn)(GObject*); typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*); typedef void (*GtkPlugEmbeddedFn)(GtkPlug*); @@ -574,16 +570,17 @@ PluginModuleChild::InitGraphics() } #else // may not be necessary on all platforms #endif #ifdef MOZ_X11 // Do this after initializing GDK, or GDK will install its own handler. XRE_InstallX11ErrorHandler(); #endif + return true; } void PluginModuleChild::DeinitGraphics() { #ifdef MOZ_WIDGET_QT nsQAppInstance::Release(); @@ -687,30 +684,16 @@ PluginModuleChild::RecvSetAudioSessionDa void PluginModuleChild::QuickExit() { NS_WARNING("plugin process _exit()ing"); _exit(0); } -PCrashReporterChild* -PluginModuleChild::AllocPCrashReporter(const mozilla::dom::NativeThreadId& id, - const PRUint32& processType) -{ - return new CrashReporterChild; -} - -bool -PluginModuleChild::DeallocPCrashReporter(PCrashReporterChild* actor) -{ - delete actor; - return true; -} - void PluginModuleChild::ActorDestroy(ActorDestroyReason why) { if (AbnormalShutdown == why) { NS_WARNING("shutting down early because of crash!"); QuickExit(); } @@ -1785,21 +1768,27 @@ PluginModuleChild::AnswerNP_GetEntryPoin *_retval = mGetEntryPointsFunc(&mFunctions); return true; #else # error Please implement me for your platform #endif } bool -PluginModuleChild::AnswerNP_Initialize(NPError* _retval) +PluginModuleChild::AnswerNP_Initialize(NativeThreadId* tid, NPError* _retval) { PLUGIN_LOG_DEBUG_METHOD; AssertPluginThread(); +#ifdef MOZ_CRASHREPORTER + *tid = CrashReporter::CurrentThreadId(); +#else + *tid = 0; +#endif + #ifdef OS_WIN SetEventHooks(); #endif #ifdef MOZ_X11 // Send the parent a dup of our X socket, to act as a proxy // reference for our X resources int xSocketFd = ConnectionNumber(DefaultXDisplay());
--- a/dom/plugins/ipc/PluginModuleChild.h +++ b/dom/plugins/ipc/PluginModuleChild.h @@ -86,45 +86,39 @@ #endif typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks); typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks); typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks); typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void); namespace mozilla { -namespace dom { -class PCrashReporterChild; -} - namespace plugins { #ifdef MOZ_WIDGET_QT class NestedLoopTimer; static const int kNestedLoopDetectorIntervalMs = 90; #endif class PluginScriptableObjectChild; class PluginInstanceChild; class PluginModuleChild : public PPluginModuleChild { - typedef mozilla::dom::PCrashReporterChild PCrashReporterChild; - protected: NS_OVERRIDE virtual mozilla::ipc::RPCChannel::RacyRPCPolicy MediateRPCRace(const Message& parent, const Message& child) { return MediateRace(parent, child); } // Implement the PPluginModuleChild interface virtual bool AnswerNP_GetEntryPoints(NPError* rv); - virtual bool AnswerNP_Initialize(NPError* rv); + virtual bool AnswerNP_Initialize(NativeThreadId* tid, NPError* rv); virtual PPluginIdentifierChild* AllocPPluginIdentifier(const nsCString& aString, const int32_t& aInt, const bool& aTemporary); virtual bool RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor, @@ -169,22 +163,16 @@ protected: virtual bool AnswerNPP_GetSitesWithData(InfallibleTArray<nsCString>* aResult); virtual bool RecvSetAudioSessionData(const nsID& aId, const nsString& aDisplayName, const nsString& aIconPath); - virtual PCrashReporterChild* - AllocPCrashReporter(const mozilla::dom::NativeThreadId& id, - const PRUint32& processType); - virtual bool - DeallocPCrashReporter(PCrashReporterChild* actor); - virtual void ActorDestroy(ActorDestroyReason why); NS_NORETURN void QuickExit(); NS_OVERRIDE virtual bool RecvProcessNativeEventsInRPCCall();
--- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -51,37 +51,34 @@ #include "base/process_util.h" #include "mozilla/Preferences.h" #include "mozilla/unused.h" #include "mozilla/ipc/SyncChannel.h" #include "mozilla/plugins/PluginModuleParent.h" #include "mozilla/plugins/BrowserStreamParent.h" -#include "mozilla/dom/PCrashReporterParent.h" #include "PluginIdentifierParent.h" #include "nsAutoPtr.h" #include "nsCRT.h" #ifdef MOZ_CRASHREPORTER -#include "mozilla/dom/CrashReporterParent.h" +#include "nsExceptionHandler.h" #endif #include "nsNPAPIPlugin.h" #include "nsILocalFile.h" #ifdef XP_WIN #include "mozilla/widget/AudioSession.h" #endif using base::KillProcess; using mozilla::PluginLibrary; using mozilla::ipc::SyncChannel; -using mozilla::dom::PCrashReporterParent; -using mozilla::dom::CrashReporterParent; using namespace mozilla; using namespace mozilla::plugins; using namespace mozilla::plugins::parent; static const char kTimeoutPref[] = "dom.ipc.plugins.timeoutSecs"; static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs"; @@ -114,21 +111,23 @@ PluginModuleParent::LoadModule(const cha TimeoutChanged(kTimeoutPref, parent); return parent.forget(); } PluginModuleParent::PluginModuleParent(const char* aFilePath) : mSubprocess(new PluginProcessParent(aFilePath)) + , mPluginThread(0) , mShutdown(false) , mClearSiteDataSupported(false) , mGetSitesWithDataSupported(false) , mNPNIface(NULL) , mPlugin(NULL) + , mProcessStartTime(time(NULL)) , mTaskFactory(this) { NS_ASSERTION(mSubprocess, "Out of memory!"); if (!mIdentifiers.Init()) { NS_ERROR("Out of memory"); } @@ -157,40 +156,77 @@ PluginModuleParent::~PluginModuleParent( mSubprocess = nsnull; } Preferences::UnregisterCallback(TimeoutChanged, kTimeoutPref, this); } #ifdef MOZ_CRASHREPORTER void -PluginModuleParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes) +PluginModuleParent::WritePluginExtraDataForMinidump(const nsAString& id) { typedef nsDependentCString CS; + CrashReporter::AnnotationTable notes; + if (!notes.Init(32)) + return; + + notes.Put(CS("ProcessType"), CS("plugin")); + + char startTime[32]; + sprintf(startTime, "%lld", static_cast<PRInt64>(mProcessStartTime)); + notes.Put(CS("StartupTime"), CS(startTime)); + // Get the plugin filename, try to get just the file leafname const std::string& pluginFile = mSubprocess->GetPluginFilePath(); size_t filePos = pluginFile.rfind(FILE_PATH_SEPARATOR); if (filePos == std::string::npos) filePos = 0; else filePos++; notes.Put(CS("PluginFilename"), CS(pluginFile.substr(filePos).c_str())); //TODO: add plugin name and version: bug 539841 // (as PluginName, PluginVersion) notes.Put(CS("PluginName"), CS("")); notes.Put(CS("PluginVersion"), CS("")); - const nsString& hangID = CrashReporter()->HangID(); - if (!hangID.IsEmpty()) - notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(hangID)); + if (!mCrashNotes.IsEmpty()) + notes.Put(CS("Notes"), CS(mCrashNotes.get())); + + if (!mHangID.IsEmpty()) + notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(mHangID)); + + if (!CrashReporter::AppendExtraData(id, notes)) + NS_WARNING("problem appending plugin data to .extra"); +} + +void +PluginModuleParent::WriteExtraDataForHang() +{ + // this writes HangID + WritePluginExtraDataForMinidump(mPluginDumpID); + + CrashReporter::AnnotationTable notes; + if (!notes.Init(4)) + return; + + notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID)); + if (!CrashReporter::AppendExtraData(mBrowserDumpID, notes)) + NS_WARNING("problem appending browser data to .extra"); } #endif // MOZ_CRASHREPORTER +bool +PluginModuleParent::RecvAppendNotesToCrashReport(const nsCString& aNotes) +{ + mCrashNotes.Append(aNotes); + return true; +} + int PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule) { NS_ASSERTION(NS_IsMainThread(), "Wrong thead!"); NS_ABORT_IF_FALSE(!strcmp(aPref, kTimeoutPref), "unexpected pref callback"); PRInt32 timeoutSecs = Preferences::GetInt(kTimeoutPref, 0); @@ -207,26 +243,39 @@ PluginModuleParent::CleanupFromTimeout() if (!mShutdown) Close(); } bool PluginModuleParent::ShouldContinueFromReplyTimeout() { #ifdef MOZ_CRASHREPORTER - CrashReporterParent* crashReporter = CrashReporter(); - if (crashReporter->GeneratePairedMinidump(this)) { - mBrowserDumpID = crashReporter->ParentDumpID(); - mPluginDumpID = crashReporter->ChildDumpID(); + nsCOMPtr<nsILocalFile> pluginDump; + nsCOMPtr<nsILocalFile> browserDump; + CrashReporter::ProcessHandle child; +#ifdef XP_MACOSX + child = mSubprocess->GetChildTask(); +#else + child = OtherProcess(); +#endif + if (CrashReporter::CreatePairedMinidumps(child, + mPluginThread, + &mHangID, + getter_AddRefs(pluginDump), + getter_AddRefs(browserDump)) && + CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID) && + CrashReporter::GetIDFromMinidump(browserDump, mBrowserDumpID)) { + PLUGIN_LOG_DEBUG( - ("generated paired browser/plugin minidumps: %s/%s (ID=%s)", - NS_ConvertUTF16toUTF8(mBrowserDumpID).get(), - NS_ConvertUTF16toUTF8(mPluginDumpID).get(), - NS_ConvertUTF16toUTF8(crashReporter->HangID()).get())); - } else { + ("generated paired browser/plugin minidumps: %s/%s (ID=%s)", + NS_ConvertUTF16toUTF8(mBrowserDumpID).get(), + NS_ConvertUTF16toUTF8(mPluginDumpID).get(), + NS_ConvertUTF16toUTF8(mHangID).get())); + } + else { NS_WARNING("failed to capture paired minidumps from hang"); } #endif // this must run before the error notification from the channel, // or not at all MessageLoop::current()->PostTask( FROM_HERE, @@ -234,43 +283,31 @@ PluginModuleParent::ShouldContinueFromRe &PluginModuleParent::CleanupFromTimeout)); if (!KillProcess(OtherProcess(), 1, false)) NS_WARNING("failed to kill subprocess!"); return false; } -#ifdef MOZ_CRASHREPORTER -CrashReporterParent* -PluginModuleParent::CrashReporter() -{ - return static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]); -} -#endif - void PluginModuleParent::ActorDestroy(ActorDestroyReason why) { switch (why) { case AbnormalShutdown: { #ifdef MOZ_CRASHREPORTER - CrashReporterParent* crashReporter = CrashReporter(); - - CrashReporter::AnnotationTable notes; - notes.Init(4); - WriteExtraDataForMinidump(notes); - - if (crashReporter->GenerateCrashReport(this, ¬es)) { - mPluginDumpID = crashReporter->ChildDumpID(); + nsCOMPtr<nsILocalFile> pluginDump; + if (TakeMinidump(getter_AddRefs(pluginDump)) && + CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID)) { PLUGIN_LOG_DEBUG(("got child minidump: %s", NS_ConvertUTF16toUTF8(mPluginDumpID).get())); + WritePluginExtraDataForMinidump(mPluginDumpID); } else if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) { - crashReporter->GenerateHangCrashReport(¬es); + WriteExtraDataForHang(); } else { NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!"); } #endif mShutdown = true; // Defer the PluginCrashed method so that we don't re-enter @@ -721,17 +758,17 @@ PluginModuleParent::NP_Initialize(NPNets mNPNIface = bFuncs; if (mShutdown) { *error = NPERR_GENERIC_ERROR; return NS_ERROR_FAILURE; } - if (!CallNP_Initialize(error)) { + if (!CallNP_Initialize(&mPluginThread, error)) { return NS_ERROR_FAILURE; } else if (*error != NPERR_NO_ERROR) { return NS_OK; } SetPluginFuncs(pFuncs); @@ -745,17 +782,17 @@ PluginModuleParent::NP_Initialize(NPNets mNPNIface = bFuncs; if (mShutdown) { *error = NPERR_GENERIC_ERROR; return NS_ERROR_FAILURE; } - if (!CallNP_Initialize(error)) + if (!CallNP_Initialize(&mPluginThread, error)) return NS_ERROR_FAILURE; #if defined XP_WIN && MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN // Send the info needed to join the chrome process's audio session to the // plugin process nsID id; nsString sessionName; nsString iconPath; @@ -1032,34 +1069,16 @@ PluginModuleParent::RecvPluginHideWindow return true; #else NS_NOTREACHED( "PluginInstanceParent::RecvPluginHideWindow not implemented!"); return false; #endif } -PCrashReporterParent* -PluginModuleParent::AllocPCrashReporter(const NativeThreadId& tid, - const PRUint32& processType) -{ -#ifdef MOZ_CRASHREPORTER - return new CrashReporterParent(tid, processType); -#else - return nsnull; -#endif -} - -bool -PluginModuleParent::DeallocPCrashReporter(PCrashReporterParent* actor) -{ - delete actor; - return true; -} - bool PluginModuleParent::RecvSetCursor(const NSCursorInfo& aCursorInfo) { PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION)); #if defined(XP_MACOSX) mac_plugin_interposing::parent::OnSetCursor(aCursorInfo); return true; #else
--- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -60,21 +60,16 @@ #include "nsAutoPtr.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" #include "nsIFileStreams.h" #include "nsTObserverArray.h" #include "nsITimer.h" namespace mozilla { -namespace dom { -class PCrashReporterParent; -class CrashReporterParent; -} - namespace plugins { //----------------------------------------------------------------------------- class BrowserStreamParent; /** * PluginModuleParent * @@ -85,18 +80,16 @@ class BrowserStreamParent; * This class /also/ implements a version of the NPN API, because the * child process needs to make these calls back into Gecko proper. * This class is responsible for "actually" making those function calls. */ class PluginModuleParent : public PPluginModuleParent, PluginLibrary { private: typedef mozilla::PluginLibrary PluginLibrary; - typedef mozilla::dom::PCrashReporterParent PCrashReporterParent; - typedef mozilla::dom::CrashReporterParent CrashReporterParent; protected: virtual PPluginIdentifierParent* AllocPPluginIdentifier(const nsCString& aString, const int32_t& aInt, const bool& aTemporary); @@ -186,30 +179,27 @@ protected: bool* aBoolVal); NS_OVERRIDE virtual bool AnswerProcessSomeEvents(); NS_OVERRIDE virtual bool RecvProcessNativeEventsInRPCCall(); + virtual bool + RecvAppendNotesToCrashReport(const nsCString& aNotes); + NS_OVERRIDE virtual bool RecvPluginShowWindow(const uint32_t& aWindowId, const bool& aModal, const int32_t& aX, const int32_t& aY, const size_t& aWidth, const size_t& aHeight); NS_OVERRIDE virtual bool RecvPluginHideWindow(const uint32_t& aWindowId); - NS_OVERRIDE virtual PCrashReporterParent* - AllocPCrashReporter(const NativeThreadId& tid, - const PRUint32& processType); - NS_OVERRIDE virtual bool - DeallocPCrashReporter(PCrashReporterParent* actor); - NS_OVERRIDE virtual bool RecvSetCursor(const NSCursorInfo& aCursorInfo); NS_OVERRIDE virtual bool RecvShowCursor(const bool& aShow); NS_OVERRIDE virtual bool RecvPushCursor(const NSCursorInfo& aCursorInfo); @@ -295,49 +285,46 @@ private: uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved, NPError* error); virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge); virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& result); private: - CrashReporterParent* CrashReporter(); - -#ifdef MOZ_CRASHREPORTER - void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes); -#endif + void WritePluginExtraDataForMinidump(const nsAString& id); + void WriteExtraDataForHang(); void CleanupFromTimeout(); static int TimeoutChanged(const char* aPref, void* aModule); void NotifyPluginCrashed(); + nsCString mCrashNotes; PluginProcessParent* mSubprocess; // the plugin thread in mSubprocess NativeThreadId mPluginThread; bool mShutdown; bool mClearSiteDataSupported; bool mGetSitesWithDataSupported; const NPNetscapeFuncs* mNPNIface; nsDataHashtable<nsVoidPtrHashKey, PluginIdentifierParent*> mIdentifiers; nsNPAPIPlugin* mPlugin; + time_t mProcessStartTime; ScopedRunnableMethodFactory<PluginModuleParent> mTaskFactory; nsString mPluginDumpID; nsString mBrowserDumpID; nsString mHangID; #ifdef OS_MACOSX nsCOMPtr<nsITimer> mCATimer; nsTObserverArray<PluginInstanceParent*> mCATimerTargets; #endif #ifdef MOZ_X11 // Dup of plugin's X socket, used to scope its resources to this // object instead of the plugin process's lifetime ScopedClose mPluginXSocketFdDup; #endif - - friend class mozilla::dom::CrashReporterParent; }; } // namespace plugins } // namespace mozilla #endif // ifndef dom_plugins_PluginModuleParent_h
--- a/dom/plugins/ipc/PluginProcessChild.cpp +++ b/dom/plugins/ipc/PluginProcessChild.cpp @@ -170,10 +170,22 @@ void PluginProcessChild::CleanUp() { #ifdef XP_WIN ::OleUninitialize(); #endif nsRegion::ShutdownStatic(); } +/* static */ +void +PluginProcessChild::AppendNotesToCrashReport(const nsCString& aNotes) +{ + AssertPluginThread(); + + PluginProcessChild* p = PluginProcessChild::current(); + if (p) { + p->mPlugin.SendAppendNotesToCrashReport(aNotes); + } +} + } // namespace plugins } // namespace mozilla
--- a/dom/plugins/ipc/PluginProcessChild.h +++ b/dom/plugins/ipc/PluginProcessChild.h @@ -56,16 +56,19 @@ public: { } virtual ~PluginProcessChild() { } NS_OVERRIDE virtual bool Init(); NS_OVERRIDE virtual void CleanUp(); + // For use on the plugin thread. + static void AppendNotesToCrashReport(const nsCString& aNotes); + protected: static PluginProcessChild* current() { return static_cast<PluginProcessChild*>(ProcessChild::current()); } private: PluginModuleChild mPlugin;
--- a/ipc/testshell/TestShellParent.cpp +++ b/ipc/testshell/TestShellParent.cpp @@ -141,23 +141,8 @@ TestShellCommandParent::RunCallback(cons return JS_TRUE; } void TestShellCommandParent::ReleaseCallback() { mCallback.Release(); } - -bool -TestShellCommandParent::ExecuteCallback(const nsString& aResponse) -{ - return static_cast<TestShellParent*>(Manager())->CommandDone( - this, aResponse); -} - -void -TestShellCommandParent::ActorDestroy(ActorDestroyReason why) -{ - if (why == AbnormalShutdown) { - ExecuteCallback(EmptyString()); - } -}
--- a/ipc/testshell/TestShellParent.h +++ b/ipc/testshell/TestShellParent.h @@ -87,22 +87,19 @@ public: JSBool SetCallback(JSContext* aCx, jsval aCallback); JSBool RunCallback(const nsString& aResponse); void ReleaseCallback(); protected: - bool ExecuteCallback(const nsString& aResponse); - - void ActorDestroy(ActorDestroyReason why); - bool Recv__delete__(const nsString& aResponse) { - return ExecuteCallback(aResponse); + return static_cast<TestShellParent*>(Manager())->CommandDone( + this, aResponse); } private: JSContext* mCx; nsAutoJSValHolder mCallback; };
--- a/testing/xpcshell/xpcshell.ini +++ b/testing/xpcshell/xpcshell.ini @@ -72,19 +72,16 @@ skip-if = !debug [include:intl/locale/tests_multilocale/unit/xpcshell.ini] run-if = toolkit == "windows" || toolkit == "cocoa" [include:toolkit/crashreporter/test/unit/xpcshell.ini] skip-if = os == "linux" || !crashreporter -[include:toolkit/crashreporter/test/unit_ipc/xpcshell.ini] -skip-if = os == "linux" || !crashreporter - #XXX: we don't actually set os = maemo [include:toolkit/crashreporter/client/maemo-unit/xpcshell.ini] run-if = os == "maemo" [include:intl/locale/src/unix/tests/unit/xpcshell.ini] skip-if = toolkit == "windows" || toolkit == "cocoa" || toolkit == "os2" [include:toolkit/components/commandlines/test/unit_win/xpcshell.ini]
--- a/toolkit/crashreporter/Makefile.in +++ b/toolkit/crashreporter/Makefile.in @@ -122,11 +122,9 @@ FORCE_STATIC_LIB = 1 EXTRA_JS_MODULES = \ CrashSubmit.jsm \ $(NULL) ifdef ENABLE_TESTS TOOL_DIRS = test endif -include $(topsrcdir)/config/config.mk -include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk
--- a/toolkit/crashreporter/nsExceptionHandler.cpp +++ b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -32,19 +32,16 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "mozilla/dom/CrashReporterChild.h" -#include "nsXULAppAPI.h" - #include "nsExceptionHandler.h" #if defined(XP_WIN32) #ifdef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN #endif #include "nsIWindowsRegKey.h" @@ -110,18 +107,16 @@ CFStringRef reporterClientAppID = CFSTR( #endif #include "nsIUUIDGenerator.h" using google_breakpad::CrashGenerationServer; using google_breakpad::ClientInfo; using mozilla::Mutex; using mozilla::MutexAutoLock; -using mozilla::dom::CrashReporterChild; -using mozilla::dom::PCrashReporterChild; namespace CrashReporter { #ifdef XP_WIN32 typedef wchar_t XP_CHAR; typedef std::wstring xpstring; #define CONVERT_UTF16_TO_XP_CHAR(x) x #define CONVERT_XP_CHAR_TO_UTF16(x) x @@ -801,17 +796,17 @@ nsresult SetExceptionHandler(nsILocalFil } #endif return NS_OK; } bool GetEnabled() { - return gExceptionHandler != nsnull; + return gExceptionHandler != nsnull && !gExceptionHandler->IsOutOfProcess(); } bool GetMinidumpPath(nsAString& aPath) { if (!gExceptionHandler) return false; aPath = CONVERT_XP_CHAR_TO_UTF16(gExceptionHandler->dump_path().c_str()); @@ -1095,55 +1090,38 @@ static PLDHashOperator EnumerateEntries( nsCString entry, void* userData) { crashReporterAPIData->Append(key + NS_LITERAL_CSTRING("=") + entry + NS_LITERAL_CSTRING("\n")); return PL_DHASH_NEXT; } -static nsresult -EscapeAnnotation(const nsACString& key, nsCString& data) +nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data) { + if (!GetEnabled()) + return NS_ERROR_NOT_INITIALIZED; + if (DoFindInReadable(key, NS_LITERAL_CSTRING("=")) || DoFindInReadable(key, NS_LITERAL_CSTRING("\n"))) return NS_ERROR_INVALID_ARG; if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0"))) return NS_ERROR_INVALID_ARG; + nsCString escapedData(data); + // escape backslashes - ReplaceChar(data, NS_LITERAL_CSTRING("\\"), + ReplaceChar(escapedData, NS_LITERAL_CSTRING("\\"), NS_LITERAL_CSTRING("\\\\")); // escape newlines - ReplaceChar(data, NS_LITERAL_CSTRING("\n"), + ReplaceChar(escapedData, NS_LITERAL_CSTRING("\n"), NS_LITERAL_CSTRING("\\n")); - return NS_OK; -} - -nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data) -{ - if (!GetEnabled()) - return NS_ERROR_NOT_INITIALIZED; - nsCString escapedData(data); - nsresult rv = EscapeAnnotation(key, escapedData); - if (NS_FAILED(rv)) - return rv; - - if (XRE_GetProcessType() != GeckoProcessType_Default) { - PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter(); - if (!reporter) - return NS_ERROR_NOT_INITIALIZED; - if (!reporter->SendAnnotateCrashReport(nsCString(key), escapedData)) - return NS_ERROR_FAILURE; - return NS_OK; - } - - crashReporterAPIData_Hash->Put(key, escapedData); + nsresult rv = crashReporterAPIData_Hash->Put(key, escapedData); NS_ENSURE_SUCCESS(rv, rv); // now rebuild the file contents crashReporterAPIData->Truncate(0); crashReporterAPIData_Hash->EnumerateRead(EnumerateEntries, crashReporterAPIData); return NS_OK; @@ -1152,34 +1130,16 @@ nsresult AnnotateCrashReport(const nsACS nsresult AppendAppNotesToCrashReport(const nsACString& data) { if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED; if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0"))) return NS_ERROR_INVALID_ARG; - if (XRE_GetProcessType() != GeckoProcessType_Default) { - PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter(); - if (!reporter) - return NS_ERROR_NOT_INITIALIZED; - - // Since we don't go through AnnotateCrashReport in the parent process, - // we must ensure that the data is escaped and valid before the parent - // sees it. - nsCString escapedData(data); - nsresult rv = EscapeAnnotation(NS_LITERAL_CSTRING("Notes"), escapedData); - if (NS_FAILED(rv)) - return rv; - - if (!reporter->SendAppendAppNotes(escapedData)) - return NS_ERROR_FAILURE; - return NS_OK; - } - notesField->Append(data); return AnnotateCrashReport(NS_LITERAL_CSTRING("Notes"), *notesField); } // Returns true if found, false if not found. bool GetAnnotation(const nsACString& key, nsACString& data) { if (!gExceptionHandler) @@ -1881,17 +1841,17 @@ SetRemoteExceptionHandler(const nsACStri // crash reporting is disabled if (crashPipe.Equals(kNullNotifyPipe)) return true; NS_ABORT_IF_FALSE(!gExceptionHandler, "crash client already init'd"); gExceptionHandler = new google_breakpad:: ExceptionHandler(L"", - FPEFilter, + NULL, // no filter callback NULL, // no minidump callback NULL, // no callback context google_breakpad::ExceptionHandler::HANDLER_ALL, MiniDumpNormal, NS_ConvertASCIItoUTF16(crashPipe).BeginReading(), NULL); #ifdef XP_WIN gExceptionHandler->set_handle_debug_exceptions(true);
--- a/toolkit/crashreporter/test/Makefile.in +++ b/toolkit/crashreporter/test/Makefile.in @@ -39,17 +39,17 @@ DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ relativesrcdir = toolkit/crashreporter/test include $(DEPTH)/config/autoconf.mk MODULE = crashreporter_test -XPCSHELL_TESTS = unit unit_ipc +XPCSHELL_TESTS = unit LIBRARY_NAME = testcrasher NO_DIST_INSTALL = 1 FORCE_SHARED_LIB = 1 VPATH += \ $(srcdir)/../google-breakpad/src/processor/ \ @@ -90,10 +90,9 @@ ifneq (mobile,$(MOZ_BUILD_APP)) $(NULL) libs:: $(_BROWSER_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/browser endif libs:: $(SHARED_LIBRARY) $(EXTRA_JS_MODULES) $(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/ - $(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit_ipc/
--- a/toolkit/crashreporter/test/unit/crasher_subprocess_head.js +++ b/toolkit/crashreporter/test/unit/crasher_subprocess_head.js @@ -1,25 +1,17 @@ // enable crash reporting first let cwd = Components.classes["@mozilla.org/file/directory_service;1"] .getService(Components.interfaces.nsIProperties) .get("CurWorkD", Components.interfaces.nsILocalFile); - let crashReporter = Components.classes["@mozilla.org/toolkit/crash-reporter;1"] .getService(Components.interfaces.nsICrashReporter); - -// the crash reporter is already enabled in content processes, -// and setting the minidump path is not allowed -let processType = Components.classes["@mozilla.org/xre/runtime;1"]. - getService(Components.interfaces.nsIXULRuntime).processType; -if (processType == Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { - crashReporter.enabled = true; - crashReporter.minidumpPath = cwd; -} +crashReporter.enabled = true; +crashReporter.minidumpPath = cwd; let ios = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); let protocolHandler = ios.getProtocolHandler("resource") .QueryInterface(Components.interfaces.nsIResProtocolHandler); let curDirURI = ios.newFileURI(cwd); protocolHandler.setSubstitution("test", curDirURI); Components.utils.import("resource://test/CrashTestUtils.jsm");
--- a/toolkit/crashreporter/test/unit/head_crashreporter.js +++ b/toolkit/crashreporter/test/unit/head_crashreporter.js @@ -60,21 +60,16 @@ function do_crash(setup, callback, canRe } catch(ex) {} // on Windows we exit with a -1 status when crashing. if (!canReturnZero) { // should exit with an error (should have crashed) do_check_neq(process.exitValue, 0); } - handleMinidump(callback); -} - -function handleMinidump(callback) -{ // find minidump let minidump = null; let en = do_get_cwd().directoryEntries; while (en.hasMoreElements()) { let f = en.getNext().QueryInterface(Components.interfaces.nsILocalFile); if (f.leafName.substr(-4) == ".dmp") { minidump = f; break; @@ -101,54 +96,16 @@ function handleMinidump(callback) callback(minidump, extra); if (minidump.exists()) minidump.remove(false); if (extrafile.exists()) extrafile.remove(false); } -function do_content_crash(setup, callback) -{ - do_load_child_test_harness(); - do_test_pending(); - - // Setting the minidump path won't work in the child, so we need to do - // that here. - let crashReporter = - Components.classes["@mozilla.org/toolkit/crash-reporter;1"] - .getService(Components.interfaces.nsICrashReporter); - crashReporter.minidumpPath = do_get_cwd(); - - let headfile = do_get_file("../unit/crasher_subprocess_head.js"); - let tailfile = do_get_file("../unit/crasher_subprocess_tail.js"); - if (setup) { - if (typeof(setup) == "function") - // funky, but convenient - setup = "("+setup.toSource()+")();"; - } - - let handleCrash = function() { - try { - handleMinidump(callback); - } catch (x) { - do_report_unexpected_exception(x); - } - do_test_finished(); - }; - - sendCommand("load(\"" + headfile.path.replace(/\\/g, "/") + "\");", function() - sendCommand(setup, function() - sendCommand("load(\"" + tailfile.path.replace(/\\/g, "/") + "\");", - function() do_execute_soon(handleCrash) - ) - ) - ); -} - // Utility functions for parsing .extra files function parseKeyValuePairs(text) { var lines = text.split('\n'); var data = {}; for (let i = 0; i < lines.length; i++) { if (lines[i] == '') continue;
deleted file mode 100644 --- a/toolkit/crashreporter/test/unit_ipc/test_content_annotation.js +++ /dev/null @@ -1,22 +0,0 @@ -load("../unit/head_crashreporter.js"); - -function run_test() -{ - if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) { - dump("INFO | test_content_annotation.js | Can't test crashreporter in a non-libxul build.\n"); - return; - } - - // Try crashing with a pure virtual call - do_content_crash(function() { - crashType = CrashTestUtils.CRASH_RUNTIMEABORT; - crashReporter.annotateCrashReport("TestKey", "TestValue"); - crashReporter.appendAppNotesToCrashReport("!!!foo!!!"); - }, - function(mdump, extra) { - do_check_eq(extra.TestKey, "TestValue"); - do_check_true('StartupTime' in extra); - do_check_true('ProcessType' in extra); - do_check_neq(extra.Notes.indexOf("!!!foo!!!"), -1); - }); -} \ No newline at end of file
deleted file mode 100644 --- a/toolkit/crashreporter/test/unit_ipc/xpcshell.ini +++ /dev/null @@ -1,5 +0,0 @@ -[DEFAULT] -head = head_crashreporter.js -tail = - -[test_content_annotation.js]
--- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -354,19 +354,17 @@ XRE_InitChildProcess(int aArgc, } err = task_set_bootstrap_port(mach_task_self(), parent_message.GetTranslatedPort(0)); if (err != KERN_SUCCESS) { NS_WARNING("child task_set_bootstrap_port() failed"); return 1; } #endif - - SetupErrorHandling(aArgv[0]); - + #if defined(MOZ_CRASHREPORTER) if (aArgc < 1) return 1; const char* const crashReporterArg = aArgv[--aArgc]; # if defined(XP_WIN) || defined(XP_MACOSX) // on windows and mac, |crashReporterArg| is the named pipe on which the // server is listening for requests, or "-" if crash reporting is @@ -383,16 +381,18 @@ XRE_InitChildProcess(int aArgc, # else # error "OOP crash reporting unsupported on this platform" # endif #endif // if defined(MOZ_CRASHREPORTER) gArgv = aArgv; gArgc = aArgc; + SetupErrorHandling(aArgv[0]); + #if defined(MOZ_WIDGET_GTK2) g_thread_init(NULL); #endif #if defined(MOZ_WIDGET_QT) nsQAppInstance::AddRef(); #endif @@ -701,28 +701,26 @@ XRE_ShutdownChildProcess() // that case, we fire off an Exit() here. If we were indeed // above MessagePump::Run(), this Exit() is just superfluous. appShell->Exit(); } #endif // XP_MACOSX } namespace { +TestShellParent* gTestShellParent = nsnull; TestShellParent* GetOrCreateTestShellParent() { - ContentParent* parent = ContentParent::GetSingleton(); - if (!parent) { - return nsnull; + if (!gTestShellParent) { + ContentParent* parent = ContentParent::GetSingleton(); + NS_ENSURE_TRUE(parent, nsnull); + gTestShellParent = parent->CreateTestShell(); + NS_ENSURE_TRUE(gTestShellParent, nsnull); } - TestShellParent* testShell = parent->GetTestShellSingleton(); - if (testShell) { - return testShell; - } - testShell = parent->CreateTestShell(); - return testShell; + return gTestShellParent; } } bool XRE_SendTestShellCommand(JSContext* aCx, JSString* aCommand, void* aCallback) { @@ -751,21 +749,19 @@ XRE_GetChildGlobalObject(JSContext* aCx, { TestShellParent* tsp = GetOrCreateTestShellParent(); return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP); } bool XRE_ShutdownTestShell() { - ContentParent* cp = ContentParent::GetSingleton(PR_FALSE); - TestShellParent* tsp = cp ? cp->GetTestShellSingleton() : nsnull; - if (!tsp) + if (!gTestShellParent) return true; - return cp->DestroyTestShell(tsp); + return ContentParent::GetSingleton()->DestroyTestShell(gTestShellParent); } #ifdef MOZ_X11 void XRE_InstallX11ErrorHandler() { InstallX11ErrorHandler(); }
--- a/toolkit/xre/nsX11ErrorHandler.cpp +++ b/toolkit/xre/nsX11ErrorHandler.cpp @@ -33,16 +33,19 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsX11ErrorHandler.h" +#include "mozilla/plugins/PluginProcessChild.h" +using mozilla::plugins::PluginProcessChild; + #include "prenv.h" #include "nsXULAppAPI.h" #include "nsExceptionHandler.h" #include "nsDebug.h" #include "mozilla/X11Util.h" #include <X11/Xlib.h> @@ -148,19 +151,25 @@ X11Error(Display *display, XErrorEvent * notes.AppendInt(PRUint32(age)); notes.Append(" requests ago"); } } #ifdef MOZ_CRASHREPORTER switch (XRE_GetProcessType()) { case GeckoProcessType_Default: + CrashReporter::AppendAppNotesToCrashReport(notes); + break; case GeckoProcessType_Plugin: - case GeckoProcessType_Content: - CrashReporter::AppendAppNotesToCrashReport(notes); + if (CrashReporter::GetEnabled()) { + // This is assuming that X operations are performed on the plugin + // thread. If plugins are using X on another thread, then we'll need to + // handle that differently. + PluginProcessChild::AppendNotesToCrashReport(notes); + } break; default: ; // crash report notes not supported. } #endif #ifdef DEBUG // The resource id is unlikely to be useful in a crash report without