in folly/fibers/scripts/gdb.py [0:0]
def get_fiber_managers(only=None):
"""iterator of (mid, manager) tuples
Can filter output with "M.*" or "M" format, e.g. "2.3" for manager 2 (fiber is
ignored) or "1" for manager 1.
"""
# first check if pre-cached
if get_fiber_managers.cache:
for (mid, manager) in get_fiber_managers.cache.items():
# output only if matching filter
if not only or str(mid) in only:
yield (mid, manager)
return
# extract the unique managers from the fiber filters
only = {i.partition(".")[0] for i in only or []}
managers = collections.OrderedDict()
mgr_map = None
for evb_type in ("folly::EventBase", "folly::VirtualEventBase"):
# this can possibly return an empty map, even if it exists
try:
mgr_map = get_fiber_manager_map(evb_type)
except gdb.GdbError:
continue
# the map pretty printer knows how to extract map entries
map_pp = gdb.default_visualizer(mgr_map)
# The children are alternating pairs of (_, (evb, int))/(_, uptr<FiberManager>)
# the first entry is irrelevant, just an internal name for the pretty printer
mid = 0
for _, entry in map_pp.children():
# The "key" in this map is std::pair<EventBaseT, long>, and the long is
# almost always 0 (used for frozen options). We'll ignore it and just use
# our own internal id. We unwrap the unique_ptr, though.
if "unique_ptr" not in entry.type.tag:
mid += 1
continue
# we have a value, make sure we have a unique key
assert mid not in managers
value = gdb.default_visualizer(entry)
# Before GCC9, the stl gdb libs don't expose the unique_ptr target
# address except through the pretty printer, as the last
# space-delimited word. From GCC9 forward, the unique_ptr visualizer
# exposes a children iterator with the target address. We extract
# that address whicever way we can, then create a new gdb.Value of
# that address cast to the fibermanager type.
address = None
if callable(getattr(value, "children", None)):
for _, pointer in value.children():
address = pointer
else:
address = int(value.to_string().split(" ")[-1], 16)
if address is not None:
manager = (
gdb.Value(address)
.cast(gdb.lookup_type("folly::fibers::FiberManager").pointer())
.dereference()
)
# output only if matching filter
if not only or str(mid) in only:
yield (mid, manager)
# set cache
get_fiber_managers.cache = managers