mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-09-14 14:47:16 +00:00
Add a filter callback to CrashGenerationServer on mac
A=Rafael Ávila de Espíndola <respindola@mozilla.com> R=ted at https://bugzilla.mozilla.org/show_bug.cgi?id=732173 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@990 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
2f56276fbf
commit
b6b4451142
|
@ -37,6 +37,8 @@ namespace google_breakpad {
|
||||||
|
|
||||||
CrashGenerationServer::CrashGenerationServer(
|
CrashGenerationServer::CrashGenerationServer(
|
||||||
const char *mach_port_name,
|
const char *mach_port_name,
|
||||||
|
FilterCallback filter,
|
||||||
|
void *filter_context,
|
||||||
OnClientDumpRequestCallback dump_callback,
|
OnClientDumpRequestCallback dump_callback,
|
||||||
void *dump_context,
|
void *dump_context,
|
||||||
OnClientExitingCallback exit_callback,
|
OnClientExitingCallback exit_callback,
|
||||||
|
@ -44,6 +46,8 @@ CrashGenerationServer::CrashGenerationServer(
|
||||||
bool generate_dumps,
|
bool generate_dumps,
|
||||||
const std::string &dump_path)
|
const std::string &dump_path)
|
||||||
: dump_callback_(dump_callback),
|
: dump_callback_(dump_callback),
|
||||||
|
filter_(filter),
|
||||||
|
filter_context_(filter_context),
|
||||||
dump_context_(dump_context),
|
dump_context_(dump_context),
|
||||||
exit_callback_(exit_callback),
|
exit_callback_(exit_callback),
|
||||||
exit_context_(exit_context),
|
exit_context_(exit_context),
|
||||||
|
@ -110,7 +114,7 @@ bool CrashGenerationServer::WaitForOneMessage() {
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
std::string dump_path;
|
std::string dump_path;
|
||||||
if (generate_dumps_) {
|
if (generate_dumps_ && (!filter_ || filter_(filter_context_))) {
|
||||||
ScopedTaskSuspend suspend(remote_task);
|
ScopedTaskSuspend suspend(remote_task);
|
||||||
|
|
||||||
MinidumpGenerator generator(remote_task, handler_thread);
|
MinidumpGenerator generator(remote_task, handler_thread);
|
||||||
|
|
|
@ -65,10 +65,14 @@ class CrashGenerationServer {
|
||||||
|
|
||||||
typedef void (*OnClientExitingCallback)(void *context,
|
typedef void (*OnClientExitingCallback)(void *context,
|
||||||
const ClientInfo &client_info);
|
const ClientInfo &client_info);
|
||||||
|
// If a FilterCallback returns false, the dump will not be written.
|
||||||
|
typedef bool (*FilterCallback)(void *context);
|
||||||
|
|
||||||
// Create an instance with the given parameters.
|
// Create an instance with the given parameters.
|
||||||
//
|
//
|
||||||
// mach_port_name: Named server port to listen on.
|
// mach_port_name: Named server port to listen on.
|
||||||
|
// filter: Callback for a client to cancel writing a dump.
|
||||||
|
// filter_context: Context for the filter callback.
|
||||||
// dump_callback: Callback for a client crash dump request.
|
// dump_callback: Callback for a client crash dump request.
|
||||||
// dump_context: Context for client crash dump request callback.
|
// dump_context: Context for client crash dump request callback.
|
||||||
// exit_callback: Callback for client process exit.
|
// exit_callback: Callback for client process exit.
|
||||||
|
@ -80,6 +84,8 @@ class CrashGenerationServer {
|
||||||
// dump_path: Path for generating dumps; required only if true is
|
// dump_path: Path for generating dumps; required only if true is
|
||||||
// passed for generateDumps parameter; NULL can be passed otherwise.
|
// passed for generateDumps parameter; NULL can be passed otherwise.
|
||||||
CrashGenerationServer(const char *mach_port_name,
|
CrashGenerationServer(const char *mach_port_name,
|
||||||
|
FilterCallback filter,
|
||||||
|
void *filter_context,
|
||||||
OnClientDumpRequestCallback dump_callback,
|
OnClientDumpRequestCallback dump_callback,
|
||||||
void *dump_context,
|
void *dump_context,
|
||||||
OnClientExitingCallback exit_callback,
|
OnClientExitingCallback exit_callback,
|
||||||
|
@ -109,6 +115,9 @@ class CrashGenerationServer {
|
||||||
// if a quit message was received or if an error occurred.
|
// if a quit message was received or if an error occurred.
|
||||||
bool WaitForOneMessage();
|
bool WaitForOneMessage();
|
||||||
|
|
||||||
|
FilterCallback filter_;
|
||||||
|
void *filter_context_;
|
||||||
|
|
||||||
OnClientDumpRequestCallback dump_callback_;
|
OnClientDumpRequestCallback dump_callback_;
|
||||||
void *dump_context_;
|
void *dump_context_;
|
||||||
|
|
||||||
|
|
|
@ -84,12 +84,14 @@ public:
|
||||||
AutoTempDir temp_dir;
|
AutoTempDir temp_dir;
|
||||||
// Counter just to ensure that we don't hit the same port again
|
// Counter just to ensure that we don't hit the same port again
|
||||||
static int i;
|
static int i;
|
||||||
|
bool filter_callback_called;
|
||||||
|
|
||||||
void SetUp() {
|
void SetUp() {
|
||||||
sprintf(mach_port_name,
|
sprintf(mach_port_name,
|
||||||
"com.google.breakpad.ServerTest.%d.%d", getpid(),
|
"com.google.breakpad.ServerTest.%d.%d", getpid(),
|
||||||
CrashGenerationServerTest::i++);
|
CrashGenerationServerTest::i++);
|
||||||
child_pid = (pid_t)-1;
|
child_pid = (pid_t)-1;
|
||||||
|
filter_callback_called = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
int CrashGenerationServerTest::i = 0;
|
int CrashGenerationServerTest::i = 0;
|
||||||
|
@ -97,12 +99,14 @@ int CrashGenerationServerTest::i = 0;
|
||||||
// Test that starting and stopping a server works
|
// Test that starting and stopping a server works
|
||||||
TEST_F(CrashGenerationServerTest, testStartStopServer) {
|
TEST_F(CrashGenerationServerTest, testStartStopServer) {
|
||||||
CrashGenerationServer server(mach_port_name,
|
CrashGenerationServer server(mach_port_name,
|
||||||
NULL, // dump callback
|
NULL, // filter callback
|
||||||
NULL, // dump context
|
NULL, // filter context
|
||||||
NULL, // exit callback
|
NULL, // dump callback
|
||||||
NULL, // exit context
|
NULL, // dump context
|
||||||
false, // generate dumps
|
NULL, // exit callback
|
||||||
""); // dump path
|
NULL, // exit context
|
||||||
|
false, // generate dumps
|
||||||
|
""); // dump path
|
||||||
ASSERT_TRUE(server.Start());
|
ASSERT_TRUE(server.Start());
|
||||||
ASSERT_TRUE(server.Stop());
|
ASSERT_TRUE(server.Stop());
|
||||||
}
|
}
|
||||||
|
@ -111,6 +115,8 @@ TEST_F(CrashGenerationServerTest, testStartStopServer) {
|
||||||
// Test without actually dumping
|
// Test without actually dumping
|
||||||
TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) {
|
TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) {
|
||||||
CrashGenerationServer server(mach_port_name,
|
CrashGenerationServer server(mach_port_name,
|
||||||
|
NULL, // filter callback
|
||||||
|
NULL, // filter context
|
||||||
NULL, // dump callback
|
NULL, // dump callback
|
||||||
NULL, // dump context
|
NULL, // dump context
|
||||||
NULL, // exit callback
|
NULL, // exit callback
|
||||||
|
@ -142,7 +148,7 @@ TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpCallback(void *context, const ClientInfo &client_info,
|
void dumpCallback(void *context, const ClientInfo &client_info,
|
||||||
const std::string &file_path) {
|
const std::string &file_path) {
|
||||||
if (context) {
|
if (context) {
|
||||||
CrashGenerationServerTest* self =
|
CrashGenerationServerTest* self =
|
||||||
reinterpret_cast<CrashGenerationServerTest*>(context);
|
reinterpret_cast<CrashGenerationServerTest*>(context);
|
||||||
|
@ -161,6 +167,8 @@ void *RequestDump(void *context) {
|
||||||
// Test that actually writing a minidump works
|
// Test that actually writing a minidump works
|
||||||
TEST_F(CrashGenerationServerTest, testRequestDump) {
|
TEST_F(CrashGenerationServerTest, testRequestDump) {
|
||||||
CrashGenerationServer server(mach_port_name,
|
CrashGenerationServer server(mach_port_name,
|
||||||
|
NULL, // filter callback
|
||||||
|
NULL, // filter context
|
||||||
dumpCallback, // dump callback
|
dumpCallback, // dump callback
|
||||||
this, // dump context
|
this, // dump context
|
||||||
NULL, // exit callback
|
NULL, // exit callback
|
||||||
|
@ -209,6 +217,8 @@ static void Crasher() {
|
||||||
// the parent.
|
// the parent.
|
||||||
TEST_F(CrashGenerationServerTest, testChildProcessCrash) {
|
TEST_F(CrashGenerationServerTest, testChildProcessCrash) {
|
||||||
CrashGenerationServer server(mach_port_name,
|
CrashGenerationServer server(mach_port_name,
|
||||||
|
NULL, // filter callback
|
||||||
|
NULL, // filter context
|
||||||
dumpCallback, // dump callback
|
dumpCallback, // dump callback
|
||||||
this, // dump context
|
this, // dump context
|
||||||
NULL, // exit callback
|
NULL, // exit callback
|
||||||
|
@ -270,6 +280,8 @@ TEST_F(CrashGenerationServerTest, testChildProcessCrash) {
|
||||||
// produces a valid minidump.
|
// produces a valid minidump.
|
||||||
TEST_F(CrashGenerationServerTest, testChildProcessCrashCrossArchitecture) {
|
TEST_F(CrashGenerationServerTest, testChildProcessCrashCrossArchitecture) {
|
||||||
CrashGenerationServer server(mach_port_name,
|
CrashGenerationServer server(mach_port_name,
|
||||||
|
NULL, // filter callback
|
||||||
|
NULL, // filter context
|
||||||
dumpCallback, // dump callback
|
dumpCallback, // dump callback
|
||||||
this, // dump context
|
this, // dump context
|
||||||
NULL, // exit callback
|
NULL, // exit callback
|
||||||
|
@ -342,4 +354,45 @@ const u_int32_t kExpectedContext =
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool filter_callback(void* context) {
|
||||||
|
CrashGenerationServerTest* self =
|
||||||
|
reinterpret_cast<CrashGenerationServerTest*>(context);
|
||||||
|
self->filter_callback_called = true;
|
||||||
|
// veto dump generation
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a filter callback can veto minidump writing.
|
||||||
|
TEST_F(CrashGenerationServerTest, testFilter) {
|
||||||
|
CrashGenerationServer server(mach_port_name,
|
||||||
|
filter_callback, // filter callback
|
||||||
|
this, // filter context
|
||||||
|
dumpCallback, // dump callback
|
||||||
|
this, // dump context
|
||||||
|
NULL, // exit callback
|
||||||
|
NULL, // exit context
|
||||||
|
true, // generate dumps
|
||||||
|
temp_dir.path()); // dump path
|
||||||
|
ASSERT_TRUE(server.Start());
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
ASSERT_NE(-1, pid);
|
||||||
|
if (pid == 0) {
|
||||||
|
// Instantiate an OOP exception handler.
|
||||||
|
ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name);
|
||||||
|
Crasher();
|
||||||
|
// not reached
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
ASSERT_EQ(pid, waitpid(pid, &ret, 0));
|
||||||
|
EXPECT_FALSE(WIFEXITED(ret));
|
||||||
|
EXPECT_TRUE(server.Stop());
|
||||||
|
|
||||||
|
// check that no minidump was written
|
||||||
|
EXPECT_TRUE(last_dump_name.empty());
|
||||||
|
EXPECT_TRUE(filter_callback_called);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in a new issue