Bug 581335 - Hook up crash reporting for content process by attaching a property bag to the global observer-service notification for them. r=mfinkle

--HG--
extra : rebase_source : 880e536710b8c02995a36fa08c49d098fb05f50f
This commit is contained in:
Benjamin Smedberg 2010-11-24 08:58:21 -05:00
Родитель eaad6195a8
Коммит b7b7f07536
13 изменённых файлов: 206 добавлений и 16 удалений

Просмотреть файл

@ -98,6 +98,12 @@ interface nsIContentFrameMessageManager : nsISyncMessageSender
* Print a string to stdout.
*/
void dump(in DOMString aStr);
/**
* If leak detection is enabled, print a note to the leak log that this
* process will intentionally crash.
*/
void privateNoteIntentionalCrash();
};
[uuid(9c48d557-92fe-4edb-95fc-bfe97e77bdc3)]

Просмотреть файл

@ -307,6 +307,12 @@ nsFrameMessageManager::Dump(const nsAString& aStr)
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::PrivateNoteIntentionalCrash()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFrameMessageManager::GetContent(nsIDOMWindow** aContent)
{

Просмотреть файл

@ -180,6 +180,12 @@ nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
return NS_OK;
}
NS_IMETHODIMP
nsInProcessTabChildGlobal::PrivateNoteIntentionalCrash()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
void
nsInProcessTabChildGlobal::Disconnect()
{

Просмотреть файл

@ -77,6 +77,7 @@ public:
{
return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
}
NS_IMETHOD PrivateNoteIntentionalCrash();
NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);

Просмотреть файл

@ -43,6 +43,7 @@
#include "History.h"
#include "mozilla/ipc/TestShellParent.h"
#include "mozilla/net/NeckoParent.h"
#include "nsHashPropertyBag.h"
#include "nsIFilePicker.h"
#include "nsIWindowWatcher.h"
#include "nsIDOMWindow.h"
@ -72,6 +73,10 @@
#include "nsPermissionManager.h"
#endif
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "mozilla/dom/ExternalHelperAppParent.h"
#include "mozilla/dom/StorageParent.h"
#include "nsAccelerometer.h"
@ -123,6 +128,28 @@ ContentParent::GetSingleton(PRBool aForceNew)
return gSingleton;
}
void
ContentParent::OnChannelConnected(int32 pid)
{
ProcessHandle handle;
if (!base::OpenPrivilegedProcessHandle(pid, &handle)) {
NS_WARNING("Can't open handle to child process.");
}
else {
SetOtherProcess(handle);
}
}
namespace {
void
DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
{
XRE_GetIOMessageLoop()
->PostTask(FROM_HERE,
new DeleteTask<GeckoChildProcessHost>(aSubprocess));
}
}
void
ContentParent::ActorDestroy(ActorDestroyReason why)
{
@ -142,11 +169,32 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
mIsAlive = false;
if (obs) {
nsString context = NS_LITERAL_STRING("");
if (AbnormalShutdown == why)
context.AssignLiteral("abnormal");
obs->NotifyObservers(nsnull, "ipc:content-shutdown", context.get());
nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
props->Init();
if (AbnormalShutdown == why) {
props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), PR_TRUE);
#ifdef MOZ_CRASHREPORTER
nsAutoString dumpID;
nsCOMPtr<nsILocalFile> crashDump;
TakeMinidump(getter_AddRefs(crashDump)) &&
CrashReporter::GetIDFromMinidump(crashDump, dumpID);
if (!dumpID.IsEmpty())
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;
}
TabParent*
@ -187,6 +235,9 @@ ContentParent::ContentParent()
ContentParent::~ContentParent()
{
if (OtherProcess())
base::CloseProcessHandle(OtherProcess());
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
//If the previous content process has died, a new one could have
//been started since.
@ -268,14 +319,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(ContentParent,
nsIThreadObserver,
nsIDOMGeoPositionCallback)
namespace {
void
DeleteSubprocess(GeckoChildProcessHost* aSubprocess)
{
delete aSubprocess;
}
}
NS_IMETHODIMP
ContentParent::Observe(nsISupports* aSubject,
const char* aTopic,
@ -294,10 +337,7 @@ ContentParent::Observe(nsISupports* aSubject,
RecvRemoveGeolocationListener();
Close();
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(DeleteSubprocess, mSubprocess));
mSubprocess = nsnull;
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
}
if (!mIsAlive || !mSubprocess)

Просмотреть файл

@ -99,6 +99,7 @@ public:
bool IsAlive();
protected:
void OnChannelConnected(int32 pid);
virtual void ActorDestroy(ActorDestroyReason why);
private:

Просмотреть файл

@ -47,6 +47,8 @@ LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
DIRS = tests
EXPORTS = TabMessageUtils.h PCOMContentPermissionRequestChild.h
EXPORTS_NAMESPACES = mozilla/dom

Просмотреть файл

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "TabChild.h"
#include "mozilla/IntentionalCrash.h"
#include "mozilla/dom/PContentChild.h"
#include "mozilla/dom/PContentDialogChild.h"
#include "mozilla/layers/PLayersChild.h"
@ -997,6 +998,13 @@ TabChildGlobal::GetContent(nsIDOMWindow** aContent)
return NS_OK;
}
NS_IMETHODIMP
TabChildGlobal::PrivateNoteIntentionalCrash()
{
mozilla::NoteIntentionalCrash("tab");
return NS_OK;
}
NS_IMETHODIMP
TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
{

Просмотреть файл

@ -108,6 +108,7 @@ public:
{
return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
}
NS_IMETHOD PrivateNoteIntentionalCrash();
NS_IMETHOD AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,

53
dom/ipc/tests/Makefile.in Normal file
Просмотреть файл

@ -0,0 +1,53 @@
# ***** 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 Firefox testing code.
#
# The Initial Developer of the Original Code is
# the Mozilla Founation <http://www.mozilla.org/>.
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# 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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/ipc/tests
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
MOCHICHROME_FILES = \
test_process_error.xul \
process_error.xul \
process_error_contentscript.js \
$(NULL)
libs:: $(MOCHICHROME_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

Просмотреть файл

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
orient="vertical">
<browser id="thebrowser" type="content" remote="true" />
<script type="application/javascript"><![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm");
const ok = window.opener.wrappedJSObject.ok;
const is = window.opener.wrappedJSObject.is;
const done = window.opener.wrappedJSObject.done;
const SimpleTest = window.opener.wrappedJSObject.SimpleTest;
function crashObserver(subject, topic, data) {
is(topic, 'ipc:content-shutdown', 'Received correct observer topic.');
ok(subject instanceof Components.interfaces.nsIPropertyBag2,
'Subject implements nsIPropertyBag2.');
if ('nsICrashReporter' in Components.interfaces) {
ok(subject.getPropertyAsAString('dumpID'), "dumpID is present");
}
Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');
done();
}
Services.obs.addObserver(crashObserver, 'ipc:content-shutdown', false);
document.getElementById('thebrowser').
QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.
messageManager.loadFrameScript('chrome://mochitests/content/chrome/dom/ipc/tests/process_error_contentscript.js', true);
]]></script>
</window>

Просмотреть файл

@ -0,0 +1,7 @@
Components.utils.import("resource://gre/modules/ctypes.jsm");
privateNoteIntentionalCrash();
var zero = new ctypes.intptr_t(8);
var badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
var crash = badptr.contents;

Просмотреть файл

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script>
SimpleTest.waitForExplicitFinish();
var w = window.open('process_error.xul', '_blank', 'chrome,resizable=yes,width=400,height=600');
function done()
{
w.close();
SimpleTest.finish();
}
</script>
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;" />
</window>