summaryrefslogtreecommitdiff
path: root/aergia/aergia.py
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-07-19 23:22:13 -0600
committerbd <bdunahu@operationnull.com>2025-07-19 23:22:13 -0600
commit0c0af7dd5a9d1c30820b52f8209151f0f2d5610d (patch)
tree018652147dee18477ac89f073ccb31f4d84ee7ef /aergia/aergia.py
parentac55d9ff0b588b91202ccad72ee71e508e33ad08 (diff)
Fix a bug where inactive loops would be indexed (read desc)
Cleaned up Aergia.walk_back_until_loop to only get running event loops. Previously, this manifested as a bug. The asyncio.Process class would fork off a thread, and the event loop would be found in that thread's local variables, even though that thread was not executing that event loop. This would result in get_event_loops containing duplicate values, and affected event loops would be assigned duplicate time
Diffstat (limited to 'aergia/aergia.py')
-rwxr-xr-xaergia/aergia.py39
1 files changed, 17 insertions, 22 deletions
diff --git a/aergia/aergia.py b/aergia/aergia.py
index b7b4f35..ad283e0 100755
--- a/aergia/aergia.py
+++ b/aergia/aergia.py
@@ -175,35 +175,30 @@ class Aergia(object):
@staticmethod
def get_event_loops():
- '''Obtains each thread's event loop by relying on the fact that
- if an event loop is active, it's own `run_once' and `run_forever'
- will appear in the callstack.'''
+ '''Obtains each thread's event loop.'''
loops = []
for t in threading.enumerate():
frame = sys._current_frames().get(t.ident)
- if not frame:
- continue
- loops.extend(Aergia.walk_back_until_loops(frame))
+ if frame:
+ loop = Aergia.walk_back_until_loop(frame)
+ if loop and loop not in loops:
+ loops.append(loop)
return loops
@staticmethod
- def walk_back_until_loops(frame):
- '''Walks back the callstack until all event loops are found.'''
- loops = []
+ def walk_back_until_loop(frame):
+ '''Walks back the callstack until we are in a method named '_run_once'.
+ If this is ever true, we assume we are in an Asyncio event loop method,
+ and check to see if the 'self' variable is indeed and instance of
+ AbstractEventLoop. Return this variable if true.'''
while frame:
- loop = Aergia.find_loop_in_locals(frame.f_locals)
- if loop and loop not in loops: # Avoid duplicates
- loops.append(loop)
- frame = frame.f_back
- return loops
-
- @staticmethod
- def find_loop_in_locals(locals_dict):
- '''Given a dictionary of local variables for a stack frame,
- retrieves the asyncio loop object, if there is one.'''
- for val in locals_dict.values():
- if isinstance(val, asyncio.AbstractEventLoop):
- return val
+ if frame.f_code.co_name == '_run_once' and 'self' in frame.f_locals:
+ loop = frame.f_locals['self']
+ if isinstance(loop, asyncio.AbstractEventLoop):
+ return loop
+ else:
+ # print(frame.f_code.co_name)
+ frame = frame.f_back
return None
@staticmethod