Bug 1415290 - Check return codes in mozcrash kill_pid; r=jmaher

This commit is contained in:
Geoff Brown 2017-11-13 13:12:05 -07:00
parent 0fff13f929
commit 00ee6fdea3
2 changed files with 53 additions and 6 deletions

View File

@ -1981,11 +1981,15 @@ toolbar#nav-bar {
If parent_pid is provided, and psutil is available, returns children of
parent_pid according to psutil.
"""
rv = []
if parent_pid and HAVE_PSUTIL:
self.log.info("Determining child pids from psutil")
return [p.pid for p in psutil.Process(parent_pid).children()]
try:
rv = [p.pid for p in psutil.Process(parent_pid).children()]
except psutil.NoSuchProcess:
self.log.warning("Failed to lookup children of pid %d" % parent_pid)
return rv
rv = []
pid_re = re.compile(r'==> process \d+ launched child process (\d+)')
with open(process_log) as fd:
for line in fd:
@ -2231,6 +2235,10 @@ toolbar#nav-bar {
# until bug 913970 is fixed regarding mozrunner `wait` not returning status
# see https://bugzilla.mozilla.org/show_bug.cgi?id=913970
status = proc.wait()
if status is None:
self.log.warning("runtests.py | Failed to get app exit code - running/crashed?")
# must report an integer to process_exit()
status = 0
self.log.process_exit("Main app process", status)
runner.process_handler = None
@ -2788,7 +2796,16 @@ toolbar#nav-bar {
self.log.info('Found child pids: %s' % child_pids)
if HAVE_PSUTIL:
child_procs = [psutil.Process(pid) for pid in child_pids]
try:
browser_proc = [psutil.Process(browser_pid)]
except:
self.log.info('Failed to get proc for pid %d' % browser_pid)
browser_proc = []
try:
child_procs = [psutil.Process(pid) for pid in child_pids]
except:
self.log.info('Failed to get child procs')
child_procs = []
for pid in child_pids:
self.killAndGetStack(pid, utilityPath, debuggerInfo,
dump_screen=not debuggerInfo)
@ -2798,6 +2815,14 @@ toolbar#nav-bar {
for p in alive:
self.log.warning('failed to kill pid %d after 30s' %
p.pid)
self.killAndGetStack(browser_pid, utilityPath, debuggerInfo,
dump_screen=not debuggerInfo)
gone, alive = psutil.wait_procs(browser_proc, timeout=30)
for p in gone:
self.log.info('psutil found pid %s dead' % p.pid)
for p in alive:
self.log.warning('failed to kill pid %d after 30s' %
p.pid)
else:
self.log.error("psutil not available! Will wait 30s before "
"attempting to kill parent process. This should "
@ -2808,8 +2833,8 @@ toolbar#nav-bar {
if child_pids:
time.sleep(30)
self.killAndGetStack(browser_pid, utilityPath, debuggerInfo,
dump_screen=not debuggerInfo)
self.killAndGetStack(browser_pid, utilityPath, debuggerInfo,
dump_screen=not debuggerInfo)
class OutputHandler(object):

View File

@ -473,10 +473,32 @@ if mozinfo.isWin:
:param pid: PID of the process to terminate.
"""
PROCESS_TERMINATE = 0x0001
WAIT_OBJECT_0 = 0x0
WAIT_FAILED = -1
logger = get_logger()
handle = OpenProcess(PROCESS_TERMINATE, 0, pid)
if handle:
kernel32.TerminateProcess(handle, 1)
if kernel32.TerminateProcess(handle, 1):
# TerminateProcess is async; wait up to 30 seconds for process to
# actually terminate, then give up so that clients are not kept
# waiting indefinitely for hung processes.
status = kernel32.WaitForSingleObject(handle, 30000)
if status == WAIT_FAILED:
err = kernel32.GetLastError()
logger.warning("kill_pid(): wait failed (%d) terminating pid %d: error %d" %
(status, pid, err))
elif status != WAIT_OBJECT_0:
logger.warning("kill_pid(): wait failed (%d) terminating pid %d" %
(status, pid))
else:
err = kernel32.GetLastError()
logger.warning("kill_pid(): unable to terminate pid %d: %d" %
(pid, err))
CloseHandle(handle)
else:
err = kernel32.GetLastError()
logger.warning("kill_pid(): unable to get handle for pid %d: %d" %
(pid, err))
else:
def kill_pid(pid):
"""