Bug 1380252 - Send only the crashing thread's stack in crash pings; r?ted.mielczarek
This modifies the minidump analyzer to only output the crashing thread's stack
when invoked. This reduces the raw size of the crash ping by 50% to 70%
depending on the program state when the crash occurred. The minidump-analyzer
can still produce the complete output when invoked with the '--full' option.
MozReview-Commit-ID: 8KaITWqfBKR
--- a/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp
+++ b/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp
@@ -1,14 +1,15 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <cstdio>
+#include <cstring>
#include <fstream>
#include <string>
#include <sstream>
#include "json/json.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
@@ -26,16 +27,23 @@
#elif defined(XP_UNIX) || defined(XP_MACOSX)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
+// Path of the minidump to be analyzed.
+static string gMinidumpPath;
+
+// When set to true print out the full minidump analysis, otherwise only
+// include the crashing thread in the output.
+static bool gFullMinidump = false;
+
namespace CrashReporter {
using std::ios;
using std::ios_base;
using std::hex;
using std::ofstream;
using std::map;
using std::showbase;
@@ -268,17 +276,20 @@ ConvertProcessStateToJSON(const ProcessS
Json::Value crashInfo;
int requestingThread = aProcessState.requesting_thread();
if (aProcessState.crashed()) {
crashInfo["type"] = aProcessState.crash_reason();
crashInfo["address"] = ToHex(aProcessState.crash_address());
if (requestingThread != -1) {
- crashInfo["crashing_thread"] = requestingThread;
+ // Record the crashing thread index only if this is a full minidump
+ // and all threads' stacks are present, otherwise only the crashing
+ // thread stack is written out and this field is set to 0.
+ crashInfo["crashing_thread"] = gFullMinidump ? requestingThread : 0;
}
} else {
crashInfo["type"] = Json::Value(Json::nullValue);
// Add assertion info, if available
string assertion = aProcessState.assertion();
if (!assertion.empty()) {
crashInfo["assertion"] = assertion;
@@ -296,24 +307,35 @@ ConvertProcessStateToJSON(const ProcessS
}
aRoot["modules"] = modules;
// Threads
Json::Value threads(Json::arrayValue);
int threadCount = aProcessState.threads()->size();
- for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex) {
+ if (!gFullMinidump && (requestingThread != -1)) {
+ // Only add the crashing thread
Json::Value thread;
Json::Value stack(Json::arrayValue);
- const CallStack* rawStack = aProcessState.threads()->at(threadIndex);
+ const CallStack* rawStack = aProcessState.threads()->at(requestingThread);
ConvertStackToJSON(aProcessState, orderedModules, rawStack, stack);
thread["frames"] = stack;
threads.append(thread);
+ } else {
+ for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex) {
+ Json::Value thread;
+ Json::Value stack(Json::arrayValue);
+ const CallStack* rawStack = aProcessState.threads()->at(threadIndex);
+
+ ConvertStackToJSON(aProcessState, orderedModules, rawStack, stack);
+ thread["frames"] = stack;
+ threads.append(thread);
+ }
}
aRoot["threads"] = threads;
}
// Process the minidump file and append the JSON-formatted stack traces to
// the node specified in |aRoot|
@@ -405,33 +427,42 @@ UpdateExtraDataFile(const string &aDumpP
delete f;
}
} // namespace CrashReporter
using namespace CrashReporter;
-int main(int argc, char** argv)
-{
- string dumpPath;
-
- if (argc > 1) {
- dumpPath = argv[1];
- }
-
- if (dumpPath.empty()) {
+static void
+ParseArguments(int argc, char** argv) {
+ if (argc <= 1) {
exit(EXIT_FAILURE);
}
- if (!FileExists(dumpPath)) {
+ for (int i = 1; i < argc - 1; i++) {
+ if (strcmp(argv[i], "--full") == 0) {
+ gFullMinidump = true;
+ } else {
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ gMinidumpPath = argv[argc - 1];
+}
+
+int main(int argc, char** argv)
+{
+ ParseArguments(argc, argv);
+
+ if (!FileExists(gMinidumpPath)) {
// The dump file does not exist
- return 1;
+ exit(EXIT_FAILURE);
}
// Try processing the minidump
Json::Value root;
- if (ProcessMinidump(root, dumpPath)) {
- UpdateExtraDataFile(dumpPath, root);
+ if (ProcessMinidump(root, gMinidumpPath)) {
+ UpdateExtraDataFile(gMinidumpPath, root);
}
exit(EXIT_SUCCESS);
}