Skip to content

Commit 217ce7d

Browse files
richardsamuelsEvergreen Agent
authored andcommitted
SERVER-50354 Fix mongodb-javascript-stack gdb command to allow printing stacktraces
1 parent de3f9cd commit 217ce7d

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

buildscripts/gdb/mongo.py

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,14 @@ def first_tid(stack):
655655
class MongoDBJavaScriptStack(gdb.Command):
656656
"""Print the JavaScript stack from a MongoDB process."""
657657

658+
# Looking to test your changes to this? Really easy!
659+
# 1. install-core to build the mongo shell binary (mongo)
660+
# 2. launch it: ./path/to/bin/mongo --nodb
661+
# 3. in the shell, run: sleep(99999999999). (do not use --eval)
662+
# 4. ps ax | grep nodb to find the PID
663+
# 5. gdb -p <PID>.
664+
# 6. Run this command, mongodb-javascript-stack
665+
658666
def __init__(self):
659667
"""Initialize MongoDBJavaScriptStack."""
660668
RegisterMongoCommand.register(self, "mongodb-javascript-stack", gdb.COMMAND_STATUS)
@@ -669,6 +677,24 @@ def invoke(self, arg, _from_tty): # pylint: disable=unused-argument
669677
else:
670678
print("No JavaScript stack print done for: %s" % (main_binary_name))
671679

680+
@staticmethod
681+
def atomic_get_ptr(atomic_scope: gdb.Value):
682+
"""Fetch the underlying pointer from std::atomic."""
683+
684+
# Awkwardly, the gdb.Value type does not support a check like
685+
# `'_M_b' in atomic_scope`, so exceptions for flow control it is. :|
686+
try:
687+
# reach into std::atomic and grab the pointer. This is for libc++
688+
return atomic_scope['_M_b']['_M_p']
689+
except gdb.error:
690+
# Worst case scenario: try and use .load(), but it's probably
691+
# inlined. parse_and_eval required because you can't call methods
692+
# in gdb on the Python API
693+
return gdb.parse_and_eval(
694+
f"((std::atomic<mongo::mozjs::MozJSImplScope*> *)({atomic_scope.address}))->load()")
695+
696+
return None
697+
672698
@staticmethod
673699
def javascript_stack():
674700
"""GDB in-process python supplement."""
@@ -690,13 +716,29 @@ def javascript_stack():
690716
continue
691717

692718
try:
693-
if gdb.parse_and_eval(
694-
'mongo::mozjs::kCurrentScope && mongo::mozjs::kCurrentScope->_inOp'):
695-
gdb.execute('thread', from_tty=False, to_string=False)
696-
gdb.execute(
697-
'printf "%s\\n", ' +
698-
'mongo::mozjs::kCurrentScope->buildStackString().c_str()', from_tty=False,
699-
to_string=False)
719+
# The following block is roughly equivalent to this:
720+
# namespace mongo::mozjs {
721+
# std::atomic<MozJSImplScope*> kCurrentScope = ...;
722+
# }
723+
# if (!scope || scope->_inOp == 0) { continue; }
724+
# print(scope->buildStackString()->c_str());
725+
atomic_scope = gdb.parse_and_eval("mongo::mozjs::kCurrentScope")
726+
ptr = MongoDBJavaScriptStack.atomic_get_ptr(atomic_scope)
727+
if not ptr:
728+
continue
729+
730+
scope = ptr.dereference()
731+
if scope['_inOp'] == 0:
732+
continue
733+
734+
gdb.execute('thread', from_tty=False, to_string=False)
735+
# gdb continues to not support calling methods through Python,
736+
# so work around it by casting the raw ptr back to its type,
737+
# and calling the method through execute darkness
738+
gdb.execute(
739+
f'printf "%s\\n", ((mongo::mozjs::MozJSImplScope*)({ptr}))->buildStackString().c_str()',
740+
from_tty=False, to_string=False)
741+
700742
except gdb.error as err:
701743
print("Ignoring GDB error '%s' in javascript_stack" % str(err))
702744
continue

0 commit comments

Comments
 (0)