diff options
author | Jonathan Abrahams <jonathan@mongodb.com> | 2017-03-16 09:49:43 -0400 |
---|---|---|
committer | Jonathan Abrahams <jonathan@mongodb.com> | 2017-03-16 09:49:43 -0400 |
commit | eaf3190fd59d291bb537cd3f3edde7e6abab7466 (patch) | |
tree | 2c38296eec64decac8aae53fd79df29060a45e07 /buildscripts/gdb | |
parent | 9791e079fdf873bd09d144e04818384f92f38594 (diff) | |
download | mongo-eaf3190fd59d291bb537cd3f3edde7e6abab7466.tar.gz |
SERVER-27873 Dump a JavaScript backtrace of any code running in SpiderMonkey in hang_analyzer.py
Diffstat (limited to 'buildscripts/gdb')
-rw-r--r-- | buildscripts/gdb/mongo.py | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/buildscripts/gdb/mongo.py b/buildscripts/gdb/mongo.py index 00e45712cbc..ecf2f1469fe 100644 --- a/buildscripts/gdb/mongo.py +++ b/buildscripts/gdb/mongo.py @@ -3,6 +3,7 @@ from __future__ import print_function import gdb.printing +import os import sys try: @@ -21,6 +22,13 @@ def get_unique_ptr(obj): return obj["_M_t"]['_M_head_impl'] +def get_process_name(): + """Return the main binary we are attached to.""" + # The return from gdb.objfiles() could include the file extension of the debug symbols. + main_binary_name = gdb.objfiles()[0].filename + return os.path.splitext(os.path.basename(main_binary_name))[0] + + ################################################################################################### # # Pretty-Printers @@ -336,12 +344,8 @@ class MongoDBAnalyze(gdb.Command): def invoke(self, arg, _from_tty): print("Running Hang Analyzer Supplement") - if len(gdb.objfiles()) == 0: - print("Skipping, not attached to an inferior") - return - - main_binary_name = gdb.objfiles()[0].filename + main_binary_name = get_process_name() if main_binary_name.endswith('mongod'): self.analyze_mongod() else: @@ -372,7 +376,7 @@ class MongoDBUniqueStack(gdb.Command): def invoke(self, arg, _from_tty): stacks = {} if not arg: - arg = 'bt' # default to 'bt' + arg = 'bt' # default to 'bt' current_thread = gdb.selected_thread() try: @@ -387,9 +391,9 @@ class MongoDBUniqueStack(gdb.Command): current_thread.switch() def _process_thread_stack(self, arg, stacks, thread): - thread_info = {} # thread dict to hold per thread data - thread_info['frames'] = [] # the complete backtrace per thread from gdb - thread_info['functions'] = [] # list of function names from frames + thread_info = {} # thread dict to hold per thread data + thread_info['frames'] = [] # the complete backtrace per thread from gdb + thread_info['functions'] = [] # list of function names from frames thread_info['pthread'] = hex(int(gdb.parse_and_eval("(uint64_t)pthread_self()"))) frame = gdb.newest_frame() @@ -422,12 +426,56 @@ class MongoDBUniqueStack(gdb.Command): print("{} duplicate thread(s):".format(len(stack['tids']) - 1), end=' ') print(", ".join((str(tid) for tid in stack['tids'][1:]))) print(stack['frames']) - print() # leave extra blank line after each thread stack + print() # leave extra blank line after each thread stack # Register command MongoDBUniqueStack() +class MongoDBJavaScriptStack(gdb.Command): + """Print the JavaScript stack from a MongoDB process""" + + def __init__(self): + register_mongo_command(self, "mongodb-javascript-stack", gdb.COMMAND_STATUS) + + def invoke(self, arg, _from_tty): + print("Running Print JavaScript Stack Supplement") + + main_binary_name = get_process_name() + if main_binary_name.endswith('mongod') or main_binary_name.endswith('mongo'): + self.javascript_stack() + else: + print("No JavaScript stack print done for: %s" % (main_binary_name)) + + def javascript_stack(self): + """GDB in-process python supplement""" + + for thread in gdb.selected_inferior().threads(): + try: + if not thread.is_valid(): + print("Ignoring invalid thread %d in javascript_stack" % thread.num) + continue + thread.switch() + except gdb.error as err: + print("Ignoring GDB error '%s' in javascript_stack" % str(err)) + continue + + try: + if gdb.parse_and_eval( + 'mongo::mozjs::kCurrentScope && mongo::mozjs::kCurrentScope->_inOp'): + gdb.execute('thread', from_tty=False, to_string=False) + gdb.execute('printf "%s\n", ' + + 'mongo::mozjs::kCurrentScope->buildStackString().c_str()', + from_tty=False, to_string=False) + except gdb.error as err: + print("Ignoring GDB error '%s' in javascript_stack" % str(err)) + continue + + +# Register command +MongoDBJavaScriptStack() + + class MongoDBHelp(gdb.Command): """Dump list of mongodb commands""" |