bug 376721 - send time-since-last-crash with crash report. r=bsmedberg/mento

This commit is contained in:
ted.mielczarek@gmail.com 2007-08-29 12:46:00 -07:00
Родитель bd21cadd28
Коммит c87eb1624b
1 изменённых файлов: 137 добавлений и 12 удалений

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

@ -88,6 +88,11 @@ typedef wchar_t XP_CHAR;
#define XP_PATH_MAX 4096
// "<reporter path>" "<minidump path>"
#define CMDLINE_SIZE ((XP_PATH_MAX * 2) + 6)
#ifdef _USE_32BIT_TIME_T
#define XP_TTOA(time, buffer, base) ltoa(time, buffer, base)
#else
#define XP_TTOA(time, buffer, base) _i64toa(time, buffer, base)
#endif
#else
typedef char XP_CHAR;
#define TO_NEW_XP_CHAR(x) ToNewUTF8String(x)
@ -97,6 +102,7 @@ typedef char XP_CHAR;
#define PATH_SEPARATOR "/"
#define XP_PATH_SEPARATOR "/"
#define XP_PATH_MAX PATH_MAX
#define XP_TTOA(time, buffer, base) sprintf(buffer, "%ld", time)
#endif // XP_WIN32
static const XP_CHAR dumpFileExtension[] = {'.', 'd', 'm', 'p',
@ -114,6 +120,19 @@ static bool doReport = true;
// if this is true, we pass the exception on to the OS crash reporter
static bool showOSCrashReporter = false;
// The time of the last recorded crash, as a time_t value.
static time_t lastCrashTime = 0;
// The pathname of a file to store the crash time in
static XP_CHAR lastCrashTimeFilename[XP_PATH_MAX] = {0};
// these are just here for readability
static const char kCrashTimeParameter[] = "CrashTime=";
static const int kCrashTimeParameterLen = sizeof(kCrashTimeParameter)-1;
static const char kTimeSinceLastCrashParameter[] = "SecondsSinceLastCrash=";
static const int kTimeSinceLastCrashParameterLen =
sizeof(kTimeSinceLastCrashParameter)-1;
// this holds additional data sent via the API
static nsDataHashtable<nsCStringHashKey,nsCString>* crashReporterAPIData_Hash;
static nsCString* crashReporterAPIData = nsnull;
@ -157,7 +176,46 @@ bool MinidumpCallback(const XP_CHAR* dump_path,
p = Concat(p, minidump_id, &size);
Concat(p, extraFileExtension, &size);
#ifdef XP_WIN32
// calculate time since last crash (if possible), and store
// the time of this crash.
time_t crashTime = time(NULL);
time_t timeSinceLastCrash = 0;
// stringified versions of the above
char crashTimeString[32];
int crashTimeStringLen = 0;
char timeSinceLastCrashString[32];
int timeSinceLastCrashStringLen = 0;
XP_TTOA(crashTime, crashTimeString, 10);
crashTimeStringLen = strlen(crashTimeString);
if (lastCrashTime != 0) {
timeSinceLastCrash = crashTime - lastCrashTime;
XP_TTOA(timeSinceLastCrash, timeSinceLastCrashString, 10);
timeSinceLastCrashStringLen = strlen(timeSinceLastCrashString);
}
// write crash time to file
if (lastCrashTimeFilename[0] != 0) {
#if defined(XP_WIN32)
HANDLE hFile = CreateFile(lastCrashTimeFilename, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile != INVALID_HANDLE_VALUE) {
DWORD nBytes;
WriteFile(hFile, crashTimeString, crashTimeStringLen, &nBytes, NULL);
CloseHandle(hFile);
}
#elif defined(XP_UNIX)
int fd = open(lastCrashTimeFilename,
O_WRONLY | O_CREAT | O_TRUNC,
0600);
if (fd != -1) {
write(fd, crashTimeString, crashTimeStringLen);
close(fd);
}
#endif
}
#if defined(XP_WIN32)
XP_CHAR cmdLine[CMDLINE_SIZE];
size = CMDLINE_SIZE;
p = Concat(cmdLine, L"\"", &size);
@ -175,6 +233,17 @@ bool MinidumpCallback(const XP_CHAR* dump_path,
DWORD nBytes;
WriteFile(hFile, crashReporterAPIData->get(),
crashReporterAPIData->Length(), &nBytes, NULL);
WriteFile(hFile, kCrashTimeParameter, kCrashTimeParameterLen,
&nBytes, NULL);
WriteFile(hFile, crashTimeString, crashTimeStringLen, &nBytes, NULL);
WriteFile(hFile, "\n", 1, &nBytes, NULL);
if (timeSinceLastCrash != 0) {
WriteFile(hFile, kTimeSinceLastCrashParameter,
kTimeSinceLastCrashParameterLen, &nBytes, NULL);
WriteFile(hFile, timeSinceLastCrashString, timeSinceLastCrashStringLen,
&nBytes, NULL);
WriteFile(hFile, "\n", 1, &nBytes, NULL);
}
CloseHandle(hFile);
}
}
@ -209,6 +278,14 @@ bool MinidumpCallback(const XP_CHAR* dump_path,
if (fd != -1) {
// not much we can do in case of error
write(fd, crashReporterAPIData->get(), crashReporterAPIData->Length());
write(fd, kCrashTimeParameter, kCrashTimeParameterLen);
write(fd, crashTimeString, crashTimeStringLen);
write(fd, "\n", 1);
if (timeSinceLastCrash != 0) {
write(fd, kTimeSinceLastCrashParameter,kTimeSinceLastCrashParameterLen);
write(fd, timeSinceLastCrashString, timeSinceLastCrashStringLen);
write(fd, "\n", 1);
}
close (fd);
}
}
@ -400,7 +477,7 @@ typedef nsresult (*InitDataFunc)(nsACString&);
// does not exist, create it and initialize its contents
// by calling aInitFunc for the data.
static nsresult
GetOrInit(nsILocalFile* aDir, const nsAString& filename,
GetOrInit(nsIFile* aDir, const nsAString& filename,
nsACString& aContents, InitDataFunc aInitFunc)
{
PRBool exists;
@ -416,10 +493,16 @@ GetOrInit(nsILocalFile* aDir, const nsAString& filename,
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
// get the initial value and write it to the file
rv = aInitFunc(aContents);
NS_ENSURE_SUCCESS(rv, rv);
rv = WriteDataToFile(dataFile, aContents);
if (aInitFunc) {
// get the initial value and write it to the file
rv = aInitFunc(aContents);
NS_ENSURE_SUCCESS(rv, rv);
rv = WriteDataToFile(dataFile, aContents);
}
else {
// didn't pass in an init func
rv = NS_ERROR_FAILURE;
}
}
else {
// just get the file's contents
@ -479,27 +562,69 @@ InitInstallTime(nsACString& aInstallTime)
return NS_OK;
}
// Annotate the crash report with a Unique User ID.
// TODO: also add time since install, and time since last crash.
// (bug 376720 and bug 376721)
// Annotate the crash report with a Unique User ID and time
// since install. Also do some prep work for recording
// time since last crash, which must be calculated at
// crash time.
// If any piece of data doesn't exist, initialize it first.
nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
const nsACString& aBuildID)
{
nsresult rv = aAppDataDirectory->Append(NS_LITERAL_STRING("Crash Reports"));
nsCOMPtr<nsIFile> dataDirectory;
nsresult rv = aAppDataDirectory->Clone(getter_AddRefs(dataDirectory));
NS_ENSURE_SUCCESS(rv, rv);
rv = dataDirectory->Append(NS_LITERAL_STRING("Crash Reports"));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString data;
if(NS_SUCCEEDED(GetOrInit(aAppDataDirectory, NS_LITERAL_STRING("UserID"),
if(NS_SUCCEEDED(GetOrInit(dataDirectory, NS_LITERAL_STRING("UserID"),
data, InitUserID)))
AnnotateCrashReport(NS_LITERAL_CSTRING("UserID"), data);
if(NS_SUCCEEDED(GetOrInit(aAppDataDirectory,
if(NS_SUCCEEDED(GetOrInit(dataDirectory,
NS_LITERAL_STRING("InstallTime") +
NS_ConvertASCIItoUTF16(aBuildID),
data, InitInstallTime)))
AnnotateCrashReport(NS_LITERAL_CSTRING("InstallTime"), data);
// this is a little different, since we can't init it with anything,
// since it's stored at crash time, and we can't annotate the
// crash report with the stored value, since we really want
// (now - LastCrash), so we just get a value if it exists,
// and store it in a time_t value.
if(NS_SUCCEEDED(GetOrInit(dataDirectory, NS_LITERAL_STRING("LastCrash"),
data, NULL))) {
lastCrashTime = (time_t)atol(data.get());
}
// not really the best place to init this, but I have the path I need here
nsCOMPtr<nsIFile> lastCrashFile;
rv = dataDirectory->Clone(getter_AddRefs(lastCrashFile));
NS_ENSURE_SUCCESS(rv, rv);
rv = lastCrashFile->Append(NS_LITERAL_STRING("LastCrash"));
NS_ENSURE_SUCCESS(rv, rv);
memset(lastCrashTimeFilename, 0, sizeof(lastCrashTimeFilename));
#if defined(XP_WIN32)
nsAutoString filename;
rv = lastCrashFile->GetPath(filename);
NS_ENSURE_SUCCESS(rv, rv);
if (filename.Length() < XP_PATH_MAX)
wcsncpy(lastCrashTimeFilename, filename.get(), filename.Length());
#else
nsCAutoString filename;
rv = lastCrashFile->GetNativePath(filename);
NS_ENSURE_SUCCESS(rv, rv);
if (filename.Length() < XP_PATH_MAX)
strncpy(lastCrashTimeFilename, filename.get(), filename.Length());
#endif
return NS_OK;
}