Commit 77ab1491 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Apply black formatter to .py files

Summary: [Folly] Apply `black` formatter to `.py` files.

Reviewed By: zertosh

Differential Revision: D17898404

fbshipit-source-id: b597b55b646e539a288d175e0b2db8111b5b103b
parent d2c64d94
...@@ -4,7 +4,7 @@ from __future__ import division ...@@ -4,7 +4,7 @@ from __future__ import division
from __future__ import print_function from __future__ import print_function
from __future__ import unicode_literals from __future__ import unicode_literals
'fbcode_builder steps to build & test folly' "fbcode_builder steps to build & test folly"
import specs.fmt as fmt import specs.fmt as fmt
import specs.gmock as gmock import specs.gmock as gmock
...@@ -14,29 +14,27 @@ from shell_quoting import ShellQuoted ...@@ -14,29 +14,27 @@ from shell_quoting import ShellQuoted
def fbcode_builder_spec(builder): def fbcode_builder_spec(builder):
builder.add_option( builder.add_option(
'folly/_build:cmake_defines', "folly/_build:cmake_defines", {"BUILD_SHARED_LIBS": "OFF", "BUILD_TESTS": "ON"}
{
'BUILD_SHARED_LIBS': 'OFF',
'BUILD_TESTS': 'ON',
}
) )
return { return {
'depends_on': [fmt, gmock], "depends_on": [fmt, gmock],
'steps': [ "steps": [
builder.fb_github_cmake_install('folly/_build'), builder.fb_github_cmake_install("folly/_build"),
builder.step( builder.step(
'Run folly tests', [ "Run folly tests",
[
builder.run( builder.run(
ShellQuoted('ctest --output-on-failure -j {n}') ShellQuoted("ctest --output-on-failure -j {n}").format(
.format(n=builder.option('make_parallelism'), ) n=builder.option("make_parallelism")
)
) )
] ],
), ),
] ],
} }
config = { config = {
'github_project': 'facebook/folly', "github_project": "facebook/folly",
'fbcode_builder_spec': fbcode_builder_spec, "fbcode_builder_spec": fbcode_builder_spec,
} }
...@@ -7,10 +7,10 @@ import re ...@@ -7,10 +7,10 @@ import re
class DiGraph(object): class DiGraph(object):
''' """
Adapted from networkx: http://networkx.github.io/ Adapted from networkx: http://networkx.github.io/
Represents a directed graph. Edges can store (key, value) attributes. Represents a directed graph. Edges can store (key, value) attributes.
''' """
def __init__(self): def __init__(self):
# Map of node -> set of nodes # Map of node -> set of nodes
...@@ -57,36 +57,36 @@ class DiGraph(object): ...@@ -57,36 +57,36 @@ class DiGraph(object):
return graph return graph
def node_link_data(self): def node_link_data(self):
''' """
Returns the graph as a dictionary in a format that can be Returns the graph as a dictionary in a format that can be
serialized. serialized.
''' """
data = { data = {
'directed': True, "directed": True,
'multigraph': False, "multigraph": False,
'graph': {}, "graph": {},
'links': [], "links": [],
'nodes': [], "nodes": [],
} }
# Do one pass to build a map of node -> position in nodes # Do one pass to build a map of node -> position in nodes
node_to_number = {} node_to_number = {}
for node in self.adjacency_map.keys(): for node in self.adjacency_map.keys():
node_to_number[node] = len(data['nodes']) node_to_number[node] = len(data["nodes"])
data['nodes'].append({'id': node}) data["nodes"].append({"id": node})
# Do another pass to build the link information # Do another pass to build the link information
for node, neighbors in self.adjacency_map.items(): for node, neighbors in self.adjacency_map.items():
for neighbor in neighbors: for neighbor in neighbors:
link = self.attributes_map[(node, neighbor)].copy() link = self.attributes_map[(node, neighbor)].copy()
link['source'] = node_to_number[node] link["source"] = node_to_number[node]
link['target'] = node_to_number[neighbor] link["target"] = node_to_number[neighbor]
data['links'].append(link) data["links"].append(link)
return data return data
def strongly_connected_components(G): # noqa: C901 def strongly_connected_components(G): # noqa: C901
''' """
Adapted from networkx: http://networkx.github.io/ Adapted from networkx: http://networkx.github.io/
Parameters Parameters
---------- ----------
...@@ -96,7 +96,7 @@ def strongly_connected_components(G): # noqa: C901 ...@@ -96,7 +96,7 @@ def strongly_connected_components(G): # noqa: C901
comp : generator of sets comp : generator of sets
A generator of sets of nodes, one for each strongly connected A generator of sets of nodes, one for each strongly connected
component of G. component of G.
''' """
preorder = {} preorder = {}
lowlink = {} lowlink = {}
scc_found = {} scc_found = {}
...@@ -129,9 +129,7 @@ def strongly_connected_components(G): # noqa: C901 ...@@ -129,9 +129,7 @@ def strongly_connected_components(G): # noqa: C901
if lowlink[v] == preorder[v]: if lowlink[v] == preorder[v]:
scc_found[v] = True scc_found[v] = True
scc = {v} scc = {v}
while ( while scc_queue and preorder[scc_queue[-1]] > preorder[v]:
scc_queue and preorder[scc_queue[-1]] > preorder[v]
):
k = scc_queue.pop() k = scc_queue.pop()
scc_found[k] = True scc_found[k] = True
scc.add(k) scc.add(k)
...@@ -141,7 +139,7 @@ def strongly_connected_components(G): # noqa: C901 ...@@ -141,7 +139,7 @@ def strongly_connected_components(G): # noqa: C901
def simple_cycles(G): # noqa: C901 def simple_cycles(G): # noqa: C901
''' """
Adapted from networkx: http://networkx.github.io/ Adapted from networkx: http://networkx.github.io/
Parameters Parameters
---------- ----------
...@@ -151,7 +149,7 @@ def simple_cycles(G): # noqa: C901 ...@@ -151,7 +149,7 @@ def simple_cycles(G): # noqa: C901
cycle_generator: generator cycle_generator: generator
A generator that produces elementary cycles of the graph. A generator that produces elementary cycles of the graph.
Each cycle is represented by a list of nodes along the cycle. Each cycle is represented by a list of nodes along the cycle.
''' """
def _unblock(thisnode, blocked, B): def _unblock(thisnode, blocked, B):
stack = set([thisnode]) stack = set([thisnode])
...@@ -211,12 +209,12 @@ def simple_cycles(G): # noqa: C901 ...@@ -211,12 +209,12 @@ def simple_cycles(G): # noqa: C901
def find_cycle(graph): def find_cycle(graph):
''' """
Looks for a cycle in the graph. If found, returns the first cycle. Looks for a cycle in the graph. If found, returns the first cycle.
If nodes a1, a2, ..., an are in a cycle, then this returns: If nodes a1, a2, ..., an are in a cycle, then this returns:
[(a1,a2), (a2,a3), ... (an-1,an), (an, a1)] [(a1,a2), (a2,a3), ... (an-1,an), (an, a1)]
Otherwise returns an empty list. Otherwise returns an empty list.
''' """
cycles = list(simple_cycles(graph)) cycles = list(simple_cycles(graph))
if cycles: if cycles:
nodes = cycles[0] nodes = cycles[0]
...@@ -232,22 +230,22 @@ def find_cycle(graph): ...@@ -232,22 +230,22 @@ def find_cycle(graph):
def get_stacktrace(thread_id): def get_stacktrace(thread_id):
''' """
Returns the stack trace for the thread id as a list of strings. Returns the stack trace for the thread id as a list of strings.
''' """
gdb.execute('thread %d' % thread_id, from_tty=False, to_string=True) gdb.execute("thread %d" % thread_id, from_tty=False, to_string=True)
output = gdb.execute('bt', from_tty=False, to_string=True) output = gdb.execute("bt", from_tty=False, to_string=True)
stacktrace_lines = output.strip().split('\n') stacktrace_lines = output.strip().split("\n")
return stacktrace_lines return stacktrace_lines
def is_thread_blocked_with_frame( def is_thread_blocked_with_frame(
thread_id, top_line, expected_top_lines, expected_frame thread_id, top_line, expected_top_lines, expected_frame
): ):
''' """
Returns True if we found expected_top_line in top_line, and Returns True if we found expected_top_line in top_line, and
we found the expected_frame in the thread's stack trace. we found the expected_frame in the thread's stack trace.
''' """
if all(expected not in top_line for expected in expected_top_lines): if all(expected not in top_line for expected in expected_top_lines):
return False return False
stacktrace_lines = get_stacktrace(thread_id) stacktrace_lines = get_stacktrace(thread_id)
...@@ -255,41 +253,39 @@ def is_thread_blocked_with_frame( ...@@ -255,41 +253,39 @@ def is_thread_blocked_with_frame(
class MutexType(Enum): class MutexType(Enum):
'''Types of mutexes that we can detect deadlocks.''' """Types of mutexes that we can detect deadlocks."""
PTHREAD_MUTEX_T = 'pthread_mutex_t' PTHREAD_MUTEX_T = "pthread_mutex_t"
PTHREAD_RWLOCK_T = 'pthread_rwlock_t' PTHREAD_RWLOCK_T = "pthread_rwlock_t"
@staticmethod @staticmethod
def get_mutex_type(thread_id, top_line): def get_mutex_type(thread_id, top_line):
''' """
Returns the probable mutex type, based on the first line Returns the probable mutex type, based on the first line
of the thread's stack. Returns None if not found. of the thread's stack. Returns None if not found.
''' """
WAITLIST = [ WAITLIST = [
'__lll_lock_wait', "__lll_lock_wait",
'futex_abstimed_wait', "futex_abstimed_wait",
'futex_abstimed_wait_cancelable', "futex_abstimed_wait_cancelable",
'futex_reltimed_wait', "futex_reltimed_wait",
'futex_reltimed_wait_cancelable', "futex_reltimed_wait_cancelable",
'futex_wait', "futex_wait",
'futex_wait_cancelable', "futex_wait_cancelable",
] ]
if is_thread_blocked_with_frame( if is_thread_blocked_with_frame(thread_id, top_line, WAITLIST, "pthread_mutex"):
thread_id, top_line, WAITLIST, 'pthread_mutex'
):
return MutexType.PTHREAD_MUTEX_T return MutexType.PTHREAD_MUTEX_T
if is_thread_blocked_with_frame( if is_thread_blocked_with_frame(
thread_id, top_line, WAITLIST, 'pthread_rwlock' thread_id, top_line, WAITLIST, "pthread_rwlock"
): ):
return MutexType.PTHREAD_RWLOCK_T return MutexType.PTHREAD_RWLOCK_T
return None return None
@staticmethod @staticmethod
def get_mutex_owner_and_address_func_for_type(mutex_type): def get_mutex_owner_and_address_func_for_type(mutex_type):
''' """
Returns a function to resolve the mutex owner and address for Returns a function to resolve the mutex owner and address for
the given type. The returned function f has the following the given type. The returned function f has the following
signature: signature:
...@@ -299,7 +295,7 @@ class MutexType(Enum): ...@@ -299,7 +295,7 @@ class MutexType(Enum):
or (None, None) if not found. or (None, None) if not found.
Returns None if there is no function for this mutex_type. Returns None if there is no function for this mutex_type.
''' """
if mutex_type == MutexType.PTHREAD_MUTEX_T: if mutex_type == MutexType.PTHREAD_MUTEX_T:
return get_pthread_mutex_t_owner_and_address return get_pthread_mutex_t_owner_and_address
if mutex_type == MutexType.PTHREAD_RWLOCK_T: if mutex_type == MutexType.PTHREAD_RWLOCK_T:
...@@ -308,33 +304,37 @@ class MutexType(Enum): ...@@ -308,33 +304,37 @@ class MutexType(Enum):
def print_cycle(graph, lwp_to_thread_id, cycle): def print_cycle(graph, lwp_to_thread_id, cycle):
'''Prints the threads and mutexes involved in the deadlock.''' """Prints the threads and mutexes involved in the deadlock."""
for (m, n) in cycle: for (m, n) in cycle:
print( print(
'Thread %d (LWP %d) is waiting on %s (0x%016x) held by ' "Thread %d (LWP %d) is waiting on %s (0x%016x) held by "
'Thread %d (LWP %d)' % ( "Thread %d (LWP %d)"
lwp_to_thread_id[m], m, % (
graph.attributes(m, n)['mutex_type'].value, lwp_to_thread_id[m],
graph.attributes(m, n)['mutex'], lwp_to_thread_id[n], n m,
graph.attributes(m, n)["mutex_type"].value,
graph.attributes(m, n)["mutex"],
lwp_to_thread_id[n],
n,
) )
) )
def get_thread_info(): def get_thread_info():
''' """
Returns a pair of: Returns a pair of:
- map of LWP -> thread ID - map of LWP -> thread ID
- map of blocked threads LWP -> potential mutex type - map of blocked threads LWP -> potential mutex type
''' """
# LWP -> thread ID # LWP -> thread ID
lwp_to_thread_id = {} lwp_to_thread_id = {}
# LWP -> potential mutex type it is blocked on # LWP -> potential mutex type it is blocked on
blocked_threads = {} blocked_threads = {}
output = gdb.execute('info threads', from_tty=False, to_string=True) output = gdb.execute("info threads", from_tty=False, to_string=True)
lines = output.strip().split('\n')[1:] lines = output.strip().split("\n")[1:]
regex = re.compile(r'[\s\*]*(\d+).*Thread.*\(LWP (\d+)\).*') regex = re.compile(r"[\s\*]*(\d+).*Thread.*\(LWP (\d+)\).*")
for line in lines: for line in lines:
try: try:
thread_id = int(regex.match(line).group(1)) thread_id = int(regex.match(line).group(1))
...@@ -350,50 +350,46 @@ def get_thread_info(): ...@@ -350,50 +350,46 @@ def get_thread_info():
def get_pthread_mutex_t_owner_and_address(lwp_to_thread_id, thread_lwp): def get_pthread_mutex_t_owner_and_address(lwp_to_thread_id, thread_lwp):
''' """
Finds the thread holding the mutex that this thread is blocked on. Finds the thread holding the mutex that this thread is blocked on.
Returns a pair of (lwp of thread owning mutex, mutex address), Returns a pair of (lwp of thread owning mutex, mutex address),
or (None, None) if not found. or (None, None) if not found.
''' """
# Go up the stack to the pthread_mutex_lock frame # Go up the stack to the pthread_mutex_lock frame
gdb.execute( gdb.execute(
'thread %d' % lwp_to_thread_id[thread_lwp], "thread %d" % lwp_to_thread_id[thread_lwp], from_tty=False, to_string=True
from_tty=False,
to_string=True
) )
gdb.execute('frame 1', from_tty=False, to_string=True) gdb.execute("frame 1", from_tty=False, to_string=True)
# Get the owner of the mutex by inspecting the internal # Get the owner of the mutex by inspecting the internal
# fields of the mutex. # fields of the mutex.
try: try:
mutex_info = gdb.parse_and_eval('mutex').dereference() mutex_info = gdb.parse_and_eval("mutex").dereference()
mutex_owner_lwp = int(mutex_info['__data']['__owner']) mutex_owner_lwp = int(mutex_info["__data"]["__owner"])
return (mutex_owner_lwp, int(mutex_info.address)) return (mutex_owner_lwp, int(mutex_info.address))
except gdb.error: except gdb.error:
return (None, None) return (None, None)
def get_pthread_rwlock_t_owner_and_address(lwp_to_thread_id, thread_lwp): def get_pthread_rwlock_t_owner_and_address(lwp_to_thread_id, thread_lwp):
''' """
If the thread is waiting on a write-locked pthread_rwlock_t, this will If the thread is waiting on a write-locked pthread_rwlock_t, this will
return the pair of: return the pair of:
(lwp of thread that is write-owning the mutex, mutex address) (lwp of thread that is write-owning the mutex, mutex address)
or (None, None) if not found, or if the mutex is read-locked. or (None, None) if not found, or if the mutex is read-locked.
''' """
# Go up the stack to the pthread_rwlock_{rd|wr}lock frame # Go up the stack to the pthread_rwlock_{rd|wr}lock frame
gdb.execute( gdb.execute(
'thread %d' % lwp_to_thread_id[thread_lwp], "thread %d" % lwp_to_thread_id[thread_lwp], from_tty=False, to_string=True
from_tty=False,
to_string=True
) )
gdb.execute('frame 2', from_tty=False, to_string=True) gdb.execute("frame 2", from_tty=False, to_string=True)
# Get the owner of the mutex by inspecting the internal # Get the owner of the mutex by inspecting the internal
# fields of the mutex. # fields of the mutex.
try: try:
rwlock_info = gdb.parse_and_eval('rwlock').dereference() rwlock_info = gdb.parse_and_eval("rwlock").dereference()
rwlock_data = rwlock_info['__data'] rwlock_data = rwlock_info["__data"]
field_names = ['__cur_writer', '__writer'] field_names = ["__cur_writer", "__writer"]
fields = rwlock_data.type.fields() fields = rwlock_data.type.fields()
field = [f for f in fields if f.name in field_names][0] field = [f for f in fields if f.name in field_names][0]
rwlock_owner_lwp = int(rwlock_data[field]) rwlock_owner_lwp = int(rwlock_data[field])
...@@ -409,13 +405,13 @@ def get_pthread_rwlock_t_owner_and_address(lwp_to_thread_id, thread_lwp): ...@@ -409,13 +405,13 @@ def get_pthread_rwlock_t_owner_and_address(lwp_to_thread_id, thread_lwp):
class Deadlock(gdb.Command): class Deadlock(gdb.Command):
'''Detects deadlocks''' """Detects deadlocks"""
def __init__(self): def __init__(self):
super(Deadlock, self).__init__('deadlock', gdb.COMMAND_NONE) super(Deadlock, self).__init__("deadlock", gdb.COMMAND_NONE)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
'''Prints the threads and mutexes in a deadlock, if it exists.''' """Prints the threads and mutexes in a deadlock, if it exists."""
lwp_to_thread_id, blocked_threads = get_thread_info() lwp_to_thread_id, blocked_threads = get_thread_info()
# Nodes represent threads. Edge (A,B) exists if thread A # Nodes represent threads. Edge (A,B) exists if thread A
...@@ -425,8 +421,9 @@ class Deadlock(gdb.Command): ...@@ -425,8 +421,9 @@ class Deadlock(gdb.Command):
# Go through all the blocked threads and see which threads # Go through all the blocked threads and see which threads
# they are blocked on, and build the thread wait graph. # they are blocked on, and build the thread wait graph.
for thread_lwp, mutex_type in blocked_threads.items(): for thread_lwp, mutex_type in blocked_threads.items():
get_owner_and_address_func = \ get_owner_and_address_func = MutexType.get_mutex_owner_and_address_func_for_type(
MutexType.get_mutex_owner_and_address_func_for_type(mutex_type) mutex_type
)
if not get_owner_and_address_func: if not get_owner_and_address_func:
continue continue
mutex_owner_lwp, mutex_address = get_owner_and_address_func( mutex_owner_lwp, mutex_address = get_owner_and_address_func(
...@@ -437,19 +434,16 @@ class Deadlock(gdb.Command): ...@@ -437,19 +434,16 @@ class Deadlock(gdb.Command):
thread_lwp, thread_lwp,
mutex_owner_lwp, mutex_owner_lwp,
mutex=mutex_address, mutex=mutex_address,
mutex_type=mutex_type mutex_type=mutex_type,
) )
# A deadlock exists if there is a cycle in the graph. # A deadlock exists if there is a cycle in the graph.
cycle = find_cycle(graph) cycle = find_cycle(graph)
if cycle: if cycle:
print('Found deadlock!') print("Found deadlock!")
print_cycle(graph, lwp_to_thread_id, cycle) print_cycle(graph, lwp_to_thread_id, cycle)
else: else:
print( print("No deadlock detected. " "Do you have debug symbols installed?")
'No deadlock detected. '
'Do you have debug symbols installed?'
)
def load(): def load():
...@@ -459,8 +453,8 @@ def load(): ...@@ -459,8 +453,8 @@ def load():
def info(): def info():
return 'Detect deadlocks' return "Detect deadlocks"
if __name__ == '__main__': if __name__ == "__main__":
load() load()
...@@ -16,7 +16,7 @@ class FiberPrinter: ...@@ -16,7 +16,7 @@ class FiberPrinter:
def __init__(self, val): def __init__(self, val):
self.val = val self.val = val
state = self.val['state_'] state = self.val["state_"]
d = gdb.types.make_enum_dict(state.type) d = gdb.types.make_enum_dict(state.type)
d = dict((v, k) for k, v in d.items()) d = dict((v, k) for k, v in d.items())
self.state = d[int(state)] self.state = d[int(state)]
...@@ -39,9 +39,11 @@ class FiberPrinter: ...@@ -39,9 +39,11 @@ class FiberPrinter:
return "Unknown" return "Unknown"
def backtrace_available(self): def backtrace_available(self):
return self.state != "folly::fibers::Fiber::INVALID" and \ return (
self.state != "folly::fibers::Fiber::NOT_STARTED" and \ self.state != "folly::fibers::Fiber::INVALID"
self.state != "folly::fibers::Fiber::RUNNING" and self.state != "folly::fibers::Fiber::NOT_STARTED"
and self.state != "folly::fibers::Fiber::RUNNING"
)
def children(self): def children(self):
result = collections.OrderedDict() result = collections.OrderedDict()
...@@ -58,17 +60,15 @@ class FiberPrinter: ...@@ -58,17 +60,15 @@ class FiberPrinter:
class GetFiberXMethodWorker(gdb.xmethod.XMethodWorker): class GetFiberXMethodWorker(gdb.xmethod.XMethodWorker):
def get_arg_types(self): def get_arg_types(self):
return gdb.lookup_type('int') return gdb.lookup_type("int")
def get_result_type(self): def get_result_type(self):
return gdb.lookup_type('int') return gdb.lookup_type("int")
def __call__(self, *args): def __call__(self, *args):
fm = args[0] fm = args[0]
index = int(args[1]) index = int(args[1])
fiber = next(itertools.islice(fiber_manager_active_fibers(fm), fiber = next(itertools.islice(fiber_manager_active_fibers(fm), index, None))
index,
None))
if fiber is None: if fiber is None:
raise gdb.GdbError("Index out of range") raise gdb.GdbError("Index out of range")
else: else:
...@@ -77,35 +77,37 @@ class GetFiberXMethodWorker(gdb.xmethod.XMethodWorker): ...@@ -77,35 +77,37 @@ class GetFiberXMethodWorker(gdb.xmethod.XMethodWorker):
class GetFiberXMethodMatcher(gdb.xmethod.XMethodMatcher): class GetFiberXMethodMatcher(gdb.xmethod.XMethodMatcher):
def __init__(self): def __init__(self):
super(GetFiberXMethodMatcher, self).__init__( super(GetFiberXMethodMatcher, self).__init__("Fiber address method matcher")
"Fiber address method matcher")
self.worker = GetFiberXMethodWorker() self.worker = GetFiberXMethodWorker()
def match(self, class_type, method_name): def match(self, class_type, method_name):
if class_type.name == "folly::fibers::FiberManager" and \ if (
method_name == "get_fiber": class_type.name == "folly::fibers::FiberManager"
and method_name == "get_fiber"
):
return self.worker return self.worker
return None return None
def fiber_manager_active_fibers(fm): def fiber_manager_active_fibers(fm):
all_fibers = \ all_fibers = fm["allFibers_"]["data_"]["root_plus_size_"]["m_header"]
fm['allFibers_']['data_']['root_plus_size_']['m_header'] fiber_hook = all_fibers["next_"]
fiber_hook = all_fibers['next_']
fiber_count = 0 fiber_count = 0
while fiber_hook != all_fibers.address: while fiber_hook != all_fibers.address:
fiber = fiber_hook.cast(gdb.lookup_type("int64_t")) fiber = fiber_hook.cast(gdb.lookup_type("int64_t"))
fiber = fiber - gdb.parse_and_eval( fiber = fiber - gdb.parse_and_eval(
"(int64_t)&'folly::fibers::Fiber'::globalListHook_") "(int64_t)&'folly::fibers::Fiber'::globalListHook_"
)
fiber = fiber.cast( fiber = fiber.cast(
gdb.lookup_type('folly::fibers::Fiber').pointer()).dereference() gdb.lookup_type("folly::fibers::Fiber").pointer()
).dereference()
if FiberPrinter(fiber).state != "folly::fibers::Fiber::INVALID": if FiberPrinter(fiber).state != "folly::fibers::Fiber::INVALID":
yield fiber yield fiber
fiber_hook = fiber_hook.dereference()['next_'] fiber_hook = fiber_hook.dereference()["next_"]
fiber_count = fiber_count + 1 fiber_count = fiber_count + 1
...@@ -123,7 +125,7 @@ class FiberManagerPrinter: ...@@ -123,7 +125,7 @@ class FiberManagerPrinter:
num_items = 0 num_items = 0
for fiber in fibers_iterator: for fiber in fibers_iterator:
if num_items >= self.fiber_print_limit: if num_items >= self.fiber_print_limit:
yield ('...', '...') yield ("...", "...")
return return
yield (str(fiber.address), fiber) yield (str(fiber.address), fiber)
...@@ -141,15 +143,18 @@ class FiberManagerPrinter: ...@@ -141,15 +143,18 @@ class FiberManagerPrinter:
class FiberPrintLimitCommand(gdb.Command): class FiberPrintLimitCommand(gdb.Command):
def __init__(self): def __init__(self):
super(FiberPrintLimitCommand, self).__init__( super(FiberPrintLimitCommand, self).__init__(
"fiber-print-limit", gdb.COMMAND_USER) "fiber-print-limit", gdb.COMMAND_USER
)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
if not arg: if not arg:
print("New limit has to be passed to 'fiber_print_limit' command") print("New limit has to be passed to 'fiber_print_limit' command")
return return
FiberManagerPrinter.fiber_print_limit = int(arg) FiberManagerPrinter.fiber_print_limit = int(arg)
print("New fiber limit for FiberManager printer set to " + print(
str(FiberManagerPrinter.fiber_print_limit)) "New fiber limit for FiberManager printer set to "
+ str(FiberManagerPrinter.fiber_print_limit)
)
class FrameId(object): class FrameId(object):
...@@ -197,8 +202,8 @@ class FiberUnwinder(gdb.unwinder.Unwinder): ...@@ -197,8 +202,8 @@ class FiberUnwinder(gdb.unwinder.Unwinder):
cls.instance = FiberUnwinder() cls.instance = FiberUnwinder()
gdb.unwinder.register_unwinder(None, cls.instance) gdb.unwinder.register_unwinder(None, cls.instance)
fiber_impl = fiber['fiberImpl_'] fiber_impl = fiber["fiberImpl_"]
cls.instance.fiber_context_ptr = fiber_impl['fiberContext_'] cls.instance.fiber_context_ptr = fiber_impl["fiberContext_"]
def __init__(self): def __init__(self):
super(FiberUnwinder, self).__init__("Fiber unwinder") super(FiberUnwinder, self).__init__("Fiber unwinder")
...@@ -208,10 +213,10 @@ class FiberUnwinder(gdb.unwinder.Unwinder): ...@@ -208,10 +213,10 @@ class FiberUnwinder(gdb.unwinder.Unwinder):
if not self.fiber_context_ptr: if not self.fiber_context_ptr:
return None return None
orig_sp = pending_frame.read_register('rsp') orig_sp = pending_frame.read_register("rsp")
orig_pc = pending_frame.read_register('rip') orig_pc = pending_frame.read_register("rip")
void_star_star = gdb.lookup_type('uint64_t').pointer() void_star_star = gdb.lookup_type("uint64_t").pointer()
ptr = self.fiber_context_ptr.cast(void_star_star) ptr = self.fiber_context_ptr.cast(void_star_star)
# This code may need to be adjusted to newer versions of boost::context. # This code may need to be adjusted to newer versions of boost::context.
...@@ -236,9 +241,9 @@ class FiberUnwinder(gdb.unwinder.Unwinder): ...@@ -236,9 +241,9 @@ class FiberUnwinder(gdb.unwinder.Unwinder):
frame_id = FrameId(rsp, orig_pc) frame_id = FrameId(rsp, orig_pc)
unwind_info = pending_frame.create_unwind_info(frame_id) unwind_info = pending_frame.create_unwind_info(frame_id)
unwind_info.add_saved_register('rbp', rbp) unwind_info.add_saved_register("rbp", rbp)
unwind_info.add_saved_register('rsp', rsp) unwind_info.add_saved_register("rsp", rsp)
unwind_info.add_saved_register('rip', rip) unwind_info.add_saved_register("rip", rip)
self.fiber_context_ptr = None self.fiber_context_ptr = None
...@@ -279,7 +284,8 @@ class FiberActivateCommand(gdb.Command): ...@@ -279,7 +284,8 @@ class FiberActivateCommand(gdb.Command):
class FiberDeactivateCommand(gdb.Command): class FiberDeactivateCommand(gdb.Command):
def __init__(self): def __init__(self):
super(FiberDeactivateCommand, self).__init__( super(FiberDeactivateCommand, self).__init__(
"fiber-deactivate", gdb.COMMAND_USER) "fiber-deactivate", gdb.COMMAND_USER
)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
print(fiber_deactivate()) print(fiber_deactivate())
...@@ -302,8 +308,7 @@ class FiberXMethodMatcher(gdb.xmethod.XMethodMatcher): ...@@ -302,8 +308,7 @@ class FiberXMethodMatcher(gdb.xmethod.XMethodMatcher):
self.worker = FiberXMethodWorker() self.worker = FiberXMethodWorker()
def match(self, class_type, method_name): def match(self, class_type, method_name):
if class_type.name == "folly::fibers::Fiber" and \ if class_type.name == "folly::fibers::Fiber" and method_name == "activate":
method_name == "activate":
return self.worker return self.worker
return None return None
...@@ -322,21 +327,26 @@ def get_fiber_manager_map(evb_type): ...@@ -322,21 +327,26 @@ def get_fiber_manager_map(evb_type):
# Exception thrown if unable to find type # Exception thrown if unable to find type
# Probably because of missing debug symbols # Probably because of missing debug symbols
global_cache_type = gdb.lookup_type( global_cache_type = gdb.lookup_type(
"folly::fibers::(anonymous namespace)::GlobalCache<" + evb_type + ">") "folly::fibers::(anonymous namespace)::GlobalCache<" + evb_type + ">"
)
except gdb.error: except gdb.error:
raise gdb.GdbError("Unable to find types. " raise gdb.GdbError(
"Unable to find types. "
"Please make sure debug info is available for this binary.\n" "Please make sure debug info is available for this binary.\n"
"Have you run 'fbload debuginfo_fbpkg'?") "Have you run 'fbload debuginfo_fbpkg'?"
)
global_cache_instance_ptr_ptr = gdb.parse_and_eval( global_cache_instance_ptr_ptr = gdb.parse_and_eval(
"&'" + global_cache_type.name + "::instance()::ret'") "&'" + global_cache_type.name + "::instance()::ret'"
)
global_cache_instance_ptr = global_cache_instance_ptr_ptr.cast( global_cache_instance_ptr = global_cache_instance_ptr_ptr.cast(
global_cache_type.pointer().pointer()).dereference() global_cache_type.pointer().pointer()
).dereference()
if global_cache_instance_ptr == 0x0: if global_cache_instance_ptr == 0x0:
raise gdb.GdbError("FiberManager map is empty.") raise gdb.GdbError("FiberManager map is empty.")
global_cache_instance = global_cache_instance_ptr.dereference() global_cache_instance = global_cache_instance_ptr.dereference()
return global_cache_instance['map_'] return global_cache_instance["map_"]
def get_fiber_manager_map_evb(): def get_fiber_manager_map_evb():
...@@ -349,9 +359,10 @@ def get_fiber_manager_map_vevb(): ...@@ -349,9 +359,10 @@ def get_fiber_manager_map_vevb():
def build_pretty_printer(): def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter("folly_fibers") pp = gdb.printing.RegexpCollectionPrettyPrinter("folly_fibers")
pp.add_printer('fibers::Fiber', '^folly::fibers::Fiber$', FiberPrinter) pp.add_printer("fibers::Fiber", "^folly::fibers::Fiber$", FiberPrinter)
pp.add_printer('fibers::FiberManager', '^folly::fibers::FiberManager$', pp.add_printer(
FiberManagerPrinter) "fibers::FiberManager", "^folly::fibers::FiberManager$", FiberManagerPrinter
)
return pp return pp
......
...@@ -14,11 +14,11 @@ class IOBufTests(unittest.TestCase): ...@@ -14,11 +14,11 @@ class IOBufTests(unittest.TestCase):
self.assertEqual(len(ebuf), 0) self.assertEqual(len(ebuf), 0)
self.assertEqual(ebuf.chain_size(), 0) self.assertEqual(ebuf.chain_size(), 0)
self.assertEqual(ebuf.chain_count(), 8) self.assertEqual(ebuf.chain_count(), 8)
self.assertEqual(b''.join(ebuf), b'') self.assertEqual(b"".join(ebuf), b"")
self.assertEqual(b'', bytes(ebuf)) self.assertEqual(b"", bytes(ebuf))
def test_chain(self) -> None: def test_chain(self) -> None:
control = [b'facebook', b'thrift', b'python3', b'cython'] control = [b"facebook", b"thrift", b"python3", b"cython"]
chain = make_chain([IOBuf(x) for x in control]) chain = make_chain([IOBuf(x) for x in control])
self.assertTrue(chain.is_chained) self.assertTrue(chain.is_chained)
self.assertTrue(chain) self.assertTrue(chain)
...@@ -27,10 +27,10 @@ class IOBufTests(unittest.TestCase): ...@@ -27,10 +27,10 @@ class IOBufTests(unittest.TestCase):
self.assertEqual(chain.chain_size(), sum(len(x) for x in control)) self.assertEqual(chain.chain_size(), sum(len(x) for x in control))
self.assertEqual(chain.chain_count(), len(control)) self.assertEqual(chain.chain_count(), len(control))
self.assertEqual(memoryview(chain.next), control[1]) # type: ignore self.assertEqual(memoryview(chain.next), control[1]) # type: ignore
self.assertEqual(b''.join(chain), b''.join(control)) self.assertEqual(b"".join(chain), b"".join(control))
def test_cyclic_chain(self) -> None: def test_cyclic_chain(self) -> None:
control = [b'aaa', b'aaaa'] control = [b"aaa", b"aaaa"]
chain = make_chain([IOBuf(x) for x in control]) chain = make_chain([IOBuf(x) for x in control])
self.assertTrue(chain.is_chained) self.assertTrue(chain.is_chained)
self.assertTrue(chain) self.assertTrue(chain)
...@@ -39,7 +39,7 @@ class IOBufTests(unittest.TestCase): ...@@ -39,7 +39,7 @@ class IOBufTests(unittest.TestCase):
self.assertEqual(chain.chain_size(), sum(len(x) for x in control)) self.assertEqual(chain.chain_size(), sum(len(x) for x in control))
self.assertEqual(chain.chain_count(), len(control)) self.assertEqual(chain.chain_count(), len(control))
self.assertEqual(memoryview(chain.next), control[1]) # type: ignore self.assertEqual(memoryview(chain.next), control[1]) # type: ignore
self.assertEqual(b''.join(chain), b''.join(control)) self.assertEqual(b"".join(chain), b"".join(control))
def test_hash(self) -> None: def test_hash(self) -> None:
x = b"omg" x = b"omg"
...@@ -61,7 +61,7 @@ class IOBufTests(unittest.TestCase): ...@@ -61,7 +61,7 @@ class IOBufTests(unittest.TestCase):
def test_iter(self) -> None: def test_iter(self) -> None:
x = b"testtest" x = b"testtest"
xb = IOBuf(x) xb = IOBuf(x)
self.assertEqual(b''.join(iter(xb)), x) self.assertEqual(b"".join(iter(xb)), x)
def test_bytes(self) -> None: def test_bytes(self) -> None:
x = b"omgwtfbbq" x = b"omgwtfbbq"
......
...@@ -11,14 +11,17 @@ from Cython.Compiler import Options ...@@ -11,14 +11,17 @@ from Cython.Compiler import Options
Options.fast_fail = True Options.fast_fail = True
ext = Extension("folly.executor", ext = Extension(
sources=['folly/executor.pyx'], "folly.executor",
libraries=['folly_pic', 'glog', 'double-conversion', 'iberty']) sources=["folly/executor.pyx"],
libraries=["folly_pic", "glog", "double-conversion", "iberty"],
)
setup(name="folly", setup(
version='0.0.1', name="folly",
packages=['folly'], version="0.0.1",
package_data={"": ['*.pxd', '*.h']}, packages=["folly"],
package_data={"": ["*.pxd", "*.h"]},
zip_safe=False, zip_safe=False,
ext_modules=cythonize([ext], ext_modules=cythonize([ext], compiler_directives={"language_level": 3}),
compiler_directives={'language_level': 3, })) )
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment