Bug 1194935 - Add a C++ implementation of kill_and_get_minidump as part of the build to accommodate dumping 64 bit Firefox from 32 bit python. r=ted

This commit is contained in:
Chris Manchester 2015-08-18 17:04:45 -07:00
parent f3e3486f03
commit 8150d56a35
6 changed files with 110 additions and 6 deletions

View File

@ -33,6 +33,7 @@ ifeq ($(OS_ARCH),WINNT)
TEST_HARNESS_BINS += \
crashinject$(BIN_SUFFIX) \
crashinjectdll$(DLL_SUFFIX) \
minidumpwriter$(BIN_SUFFIX) \
$(NULL)
endif

View File

@ -1783,7 +1783,8 @@ class MochitestDesktop(MochitestBase):
try:
minidump_path = os.path.join(self.profile.profile,
'minidumps')
mozcrash.kill_and_get_minidump(processPID, minidump_path)
mozcrash.kill_and_get_minidump(processPID, minidump_path,
utilityPath)
except OSError:
# https://bugzilla.mozilla.org/show_bug.cgi?id=921509
self.log.info(

View File

@ -364,7 +364,7 @@ if mozinfo.isWin:
OpenProcess = kernel32.OpenProcess
CloseHandle = kernel32.CloseHandle
def write_minidump(pid, dump_directory):
def write_minidump(pid, dump_directory, utility_path):
"""
Write a minidump for a process.
@ -379,13 +379,38 @@ if mozinfo.isWin:
FILE_ATTRIBUTE_NORMAL = 0x80
INVALID_HANDLE_VALUE = -1
file_name = os.path.join(dump_directory,
str(uuid.uuid4()) + ".dmp")
if (mozinfo.info['bits'] != ctypes.sizeof(ctypes.c_voidp) * 8 and
utility_path):
# We're not going to be able to write a minidump with ctypes if our
# python process was compiled for a different architecture than
# firefox, so we invoke the minidumpwriter utility program.
log = get_logger()
minidumpwriter = os.path.normpath(os.path.join(utility_path,
"minidumpwriter.exe"))
log.info("Using %s to write a dump to %s for [%d]" %
(minidumpwriter, file_name, pid))
if not os.path.exists(minidumpwriter):
log.error("minidumpwriter not found in %s" % utility_path)
return
if isinstance(file_name, unicode):
# Convert to a byte string before sending to the shell.
file_name = file_name.encode(sys.getfilesystemencoding())
status = subprocess.Popen([minidumpwriter, str(pid), file_name]).wait()
if status:
log.error("minidumpwriter exited with status: %d" % status)
return
proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
0, pid)
if not proc_handle:
return
file_name = os.path.join(dump_directory,
str(uuid.uuid4()) + ".dmp")
if not isinstance(file_name, unicode):
# Convert to unicode explicitly so our path will be valid as input
# to CreateFileW
@ -433,7 +458,7 @@ else:
"""
os.kill(pid, signal.SIGKILL)
def kill_and_get_minidump(pid, dump_directory=None):
def kill_and_get_minidump(pid, dump_directory, utility_path=None):
"""
Attempt to kill a process and leave behind a minidump describing its
execution state.
@ -453,7 +478,7 @@ def kill_and_get_minidump(pid, dump_directory=None):
"""
needs_killing = True
if mozinfo.isWin:
write_minidump(pid, dump_directory)
write_minidump(pid, dump_directory, utility_path)
elif mozinfo.isLinux or mozinfo.isMac:
os.kill(pid, signal.SIGABRT)
needs_killing = False

View File

@ -0,0 +1,59 @@
/* 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/. */
/*
* Given a PID and a path to a target file, write a minidump of the
* corresponding process in that file. This is taken more or less
* verbatim from mozcrash and translated to C++ to avoid problems
* writing a minidump of 64 bit Firefox from a 32 bit python.
*/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <dbghelp.h>
int wmain(int argc, wchar_t** argv)
{
if (argc != 3) {
fprintf(stderr, "Usage: minidumpwriter <PID> <DUMP_FILE>\n");
return 1;
}
DWORD pid = (DWORD) _wtoi(argv[1]);
if (pid <= 0) {
fprintf(stderr, "Usage: minidumpwriter <PID> <DUMP_FILE>\n");
return 1;
}
wchar_t* dumpfile = argv[2];
int rv = 1;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
0, pid);
if (!hProcess) {
fprintf(stderr, "Couldn't get handle for %d\n", pid);
return rv;
}
HANDLE file = CreateFileW(dumpfile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Couldn't open dump file at %S\n", dumpfile);
CloseHandle(hProcess);
return rv;
}
rv = 0;
if (!MiniDumpWriteDump(hProcess, pid, file, MiniDumpNormal,
nullptr, nullptr, nullptr)) {
fprintf(stderr, "Error 0x%X in MiniDumpWriteDump\n", GetLastError());
rv = 1;
}
CloseHandle(file);
CloseHandle(hProcess);
return rv;
}

View File

@ -0,0 +1,17 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
if CONFIG['ENABLE_TESTS'] and CONFIG['CPU_ARCH'] == 'x86_64' and CONFIG['OS_ARCH'] == 'WINNT':
Program('minidumpwriter')
OS_LIBS += [
'dbghelp',
]
SOURCES += [
'minidumpwriter.cpp',
]
USE_STATIC_LIBS = True
NO_PGO = True

View File

@ -172,6 +172,7 @@ if CONFIG['ENABLE_TESTS']:
DIRS += [
'/testing/mochitest',
'/testing/xpcshell',
'/testing/tools/minidumpwriter',
'/testing/tools/screenshot',
'/testing/profiles',
'/testing/mozbase',