summaryrefslogtreecommitdiff
path: root/buildscripts/hang_analyzer.py
diff options
context:
space:
mode:
authorEddie Louie <eddie.louie@mongodb.com>2017-03-24 02:22:31 -0400
committerEddie Louie <eddie.louie@mongodb.com>2017-03-31 18:21:53 -0400
commitb6d2b5e5c6071f6b76072d15bf36f34babec2a14 (patch)
treec90bf25eee33d2cd43f7d0cd991c1a2d48425475 /buildscripts/hang_analyzer.py
parentf6cbdfb8c5c52209f58562ccbe14013c72df3f40 (diff)
downloadmongo-b6d2b5e5c6071f6b76072d15bf36f34babec2a14.tar.gz
SERVER-21842 Generate report.json file and dump resmoke stacks on Windows
Diffstat (limited to 'buildscripts/hang_analyzer.py')
-rwxr-xr-xbuildscripts/hang_analyzer.py60
1 files changed, 54 insertions, 6 deletions
diff --git a/buildscripts/hang_analyzer.py b/buildscripts/hang_analyzer.py
index 45e34462fda..ffc5d6a79fa 100755
--- a/buildscripts/hang_analyzer.py
+++ b/buildscripts/hang_analyzer.py
@@ -27,6 +27,12 @@ import tempfile
import time
from distutils import spawn
from optparse import OptionParser
+_is_windows = (sys.platform == "win32")
+
+if _is_windows:
+ import win32event
+ import win32api
+
# Get relative imports to work when the package is not installed on the PYTHONPATH.
if __name__ == "__main__" and __package__ is None:
@@ -477,7 +483,7 @@ def get_hang_analyzers():
dbg = GDBDumper()
jstack = JstackDumper()
ps = SolarisProcessList()
- elif os.name == 'nt' or (os.name == "posix" and sys.platform == "cygwin"):
+ elif _is_windows or sys.platform == "cygwin":
dbg = WindowsDumper()
jstack = JstackWindowsDumper()
ps = WindowsProcessList()
@@ -501,6 +507,33 @@ def check_dump_quota(quota, ext):
return (size_sum <= quota)
+def signal_event_object(logger, pid):
+ """Signal the Windows event object"""
+
+ # Use unique event_name created.
+ event_name = "Global\\Mongo_Python_" + str(pid)
+
+ try:
+ desired_access = win32event.EVENT_MODIFY_STATE
+ inherit_handle = False
+ task_timeout_handle = win32event.OpenEvent(desired_access,
+ inherit_handle,
+ event_name)
+ except win32event.error as err:
+ logger.info("Exception from win32event.OpenEvent with error: %s" % err)
+ return
+
+ try:
+ win32event.SetEvent(task_timeout_handle)
+ except win32event.error as err:
+ logger.info("Exception from win32event.SetEvent with error: %s" % err)
+ finally:
+ win32api.CloseHandle(task_timeout_handle)
+
+ logger.info("Waiting for process to report")
+ time.sleep(5)
+
+
def signal_process(logger, pid, signalnum):
"""Signal process with signal, N/A on Windows"""
try:
@@ -530,8 +563,13 @@ def main():
root_logger.info("OS: %s" % platform.platform())
try:
- distro = platform.linux_distribution()
- root_logger.info("Linux Distribution: %s" % str(distro))
+ if _is_windows or sys.platform == "cygwin":
+ distro = platform.win32_ver()
+ root_logger.info("Windows Distribution: %s" % str(distro))
+ else:
+ distro = platform.linux_distribution()
+ root_logger.info("Linux Distribution: %s" % str(distro))
+
except AttributeError:
root_logger.warning("Cannot determine Linux distro since Python is too old")
@@ -651,13 +689,23 @@ def main():
# TerminateProcess.
# Note: The stacktrace output may be captured elsewhere (i.e. resmoke).
for (pid, process_name) in [(p, pn) for (p, pn) in processes if pn in go_processes]:
- root_logger.info("Sending signal SIGABRT to go process %s with PID %d" % (process_name, pid))
+ root_logger.info("Sending signal SIGABRT to go process %s with PID %d" %
+ (process_name, pid))
signal_process(root_logger, pid, signal.SIGABRT)
# Dump python processes after signalling them.
for (pid, process_name) in [(p, pn) for (p, pn) in processes if pn.startswith("python")]:
- root_logger.info("Sending signal SIGUSR1 to python process %s with PID %d" % (process_name, pid))
- signal_process(root_logger, pid, signal.SIGUSR1)
+ # On Windows, we set up an event object to wait on a signal. For Cygwin, we register
+ # a signal handler to wait for the signal since it supports POSIX signals.
+ if _is_windows:
+ root_logger.info("Calling SetEvent to signal python process %s with PID %d" %
+ (process_name, pid))
+ signal_event_object(root_logger, pid)
+ else:
+ root_logger.info("Sending signal SIGUSR1 to python process %s with PID %d" %
+ (process_name, pid))
+ signal_process(root_logger, pid, signal.SIGUSR1)
+
process_logger = get_process_logger(options.debugger_output, pid, process_name)
dbg.dump_info(
root_logger,