Improve get_fiber_manager_map_*() error reporting
[folly.git] / folly / fibers / scripts / gdb.py
index 1f5e9f95090924da34cb2361b23b9f735f62d7c6..a9c1e3a215b917908af059a6a127192b1aa93ca0 100644 (file)
@@ -58,6 +58,8 @@ class FiberPrinter:
 class FiberManagerPrinter:
     """Print a folly::fibers::Fiber"""
 
+    fiber_print_limit = 100
+
     def __init__(self, fm):
         self.fm = fm
 
@@ -68,10 +70,16 @@ class FiberManagerPrinter:
 
         active_fibers = collections.OrderedDict()
 
+        fiber_count = 0
+
         while fiber_hook != all_fibers.address:
+            if fiber_count == FiberManagerPrinter.fiber_print_limit:
+                active_fibers["..."] = "..."
+                break
+
             fiber = fiber_hook.cast(gdb.lookup_type("int64_t"))
             fiber = fiber - gdb.parse_and_eval(
-                "(int64_t)&folly::fibers::Fiber::globalListHook_")
+                "(int64_t)&'folly::fibers::Fiber'::globalListHook_")
             fiber = fiber.cast(
                 gdb.lookup_type('folly::fibers::Fiber').pointer()).dereference()
 
@@ -80,6 +88,8 @@ class FiberManagerPrinter:
 
             fiber_hook = fiber_hook.dereference()['next_']
 
+            fiber_count = fiber_count + 1
+
         return active_fibers.items()
 
     def to_string(self):
@@ -89,6 +99,20 @@ class FiberManagerPrinter:
         return "folly::fibers::FiberManager"
 
 
+class FiberPrintLimitCommand(gdb.Command):
+    def __init__(self):
+        super(FiberPrintLimitCommand, self).__init__(
+            "fiber-print-limit", gdb.COMMAND_USER)
+
+    def invoke(self, arg, from_tty):
+        if not arg:
+            print("New limit has to be passed to 'fiber_print_limit' command")
+            return
+        FiberManagerPrinter.fiber_print_limit = int(arg)
+        print("New fiber limit for FiberManager printer set to " +
+              str(FiberManagerPrinter.fiber_print_limit))
+
+
 class FrameId(object):
     def __init__(self, sp, pc):
         self.sp = sp
@@ -253,14 +277,25 @@ class Shortcut(gdb.Function):
 
 
 def get_fiber_manager_map(evb_type):
-    global_cache_type = gdb.lookup_type(
-        "folly::fibers::(anonymous namespace)::GlobalCache<" + evb_type + ">")
+    try:
+        # Exception thrown if unable to find type
+        # Probably because of missing debug symbols
+        global_cache_type = gdb.lookup_type(
+            "folly::fibers::(anonymous namespace)::GlobalCache<" + evb_type + ">")
+    except gdb.error:
+        raise gdb.GdbError("Unable to find types. "
+                           "Please make sure debug info is available for this binary.\n"
+                           "Have you run 'fbload debuginfo_fbpkg'?")
+
     global_cache_instance_ptr_ptr = gdb.parse_and_eval(
         "&'" + global_cache_type.name + "::instance()::ret'")
-    global_cache_instance = global_cache_instance_ptr_ptr.cast(
-        global_cache_type.pointer().pointer()).dereference().dereference()
-    return global_cache_instance['map_']
+    global_cache_instance_ptr = global_cache_instance_ptr_ptr.cast(
+        global_cache_type.pointer().pointer()).dereference()
+    if global_cache_instance_ptr == 0x0:
+        raise gdb.GdbError("FiberManager map is empty.")
 
+    global_cache_instance = global_cache_instance_ptr.dereference()
+    return global_cache_instance['map_']
 
 def get_fiber_manager_map_evb():
     return get_fiber_manager_map("folly::EventBase")
@@ -281,6 +316,7 @@ def build_pretty_printer():
 def load():
     gdb.printing.register_pretty_printer(gdb, build_pretty_printer())
     gdb.xmethod.register_xmethod_matcher(gdb, FiberXMethodMatcher())
+    FiberPrintLimitCommand()
     FiberActivateCommand()
     FiberDeactivateCommand()
     Shortcut("get_fiber_manager_map_evb", get_fiber_manager_map_evb)