|
31 | 31 | logger = logging.getLogger(__name__) |
32 | 32 |
|
33 | 33 |
|
34 | | -# class DebugLock: |
35 | | -# """A wrapper around threading.Lock that provides detailed debugging for lock acquisition/release""" |
36 | | - |
37 | | -# def __init__(self, name: str = "DebugLock"): |
38 | | -# self._lock = threading.Lock() |
39 | | -# self._name = name |
40 | | -# self._owner: Optional[str] = None |
41 | | -# self._waiters: List[str] = [] |
42 | | -# self._debug_logger = logging.getLogger(f"{__name__}.{name}") |
43 | | -# # Ensure debug logging is visible |
44 | | -# if not self._debug_logger.handlers: |
45 | | -# handler = logging.StreamHandler() |
46 | | -# formatter = logging.Formatter( |
47 | | -# ":lock: %(asctime)s [%(threadName)s-%(thread)d] LOCK-%(name)s: %(message)s" |
48 | | -# ) |
49 | | -# handler.setFormatter(formatter) |
50 | | -# self._debug_logger.addHandler(handler) |
51 | | -# self._debug_logger.setLevel(logging.DEBUG) |
52 | | - |
53 | | -# def acquire(self, blocking=True, timeout=-1): |
54 | | -# current = threading.current_thread() |
55 | | -# thread_info = f"{current.name}-{current.ident}" |
56 | | -# if self._owner: |
57 | | -# self._debug_logger.warning( |
58 | | -# f": WAITING: {thread_info} waiting for lock held by {self._owner}" |
59 | | -# ) |
60 | | -# self._waiters.append(thread_info) |
61 | | -# else: |
62 | | -# self._debug_logger.debug( |
63 | | -# f": TRYING: {thread_info} attempting to acquire lock" |
64 | | -# ) |
65 | | -# # Try to acquire the lock |
66 | | -# acquired = self._lock.acquire(blocking, timeout) |
67 | | -# if acquired: |
68 | | -# self._owner = thread_info |
69 | | -# self._debug_logger.info(f": ACQUIRED: {thread_info} got the lock") |
70 | | -# if self._waiters: |
71 | | -# self._debug_logger.info( |
72 | | -# f": WAITERS: {len(self._waiters)} threads waiting: {self._waiters}" |
73 | | -# ) |
74 | | -# else: |
75 | | -# self._debug_logger.error( |
76 | | -# f": FAILED: {thread_info} failed to acquire lock (timeout)" |
77 | | -# ) |
78 | | -# if thread_info in self._waiters: |
79 | | -# self._waiters.remove(thread_info) |
80 | | -# return acquired |
81 | | - |
82 | | -# def release(self): |
83 | | -# current = threading.current_thread() |
84 | | -# thread_info = f"{current.name}-{current.ident}" |
85 | | -# if self._owner != thread_info: |
86 | | -# self._debug_logger.error( |
87 | | -# f": ERROR: {thread_info} trying to release lock owned by {self._owner}" |
88 | | -# ) |
89 | | -# else: |
90 | | -# self._debug_logger.info(f": RELEASED: {thread_info} released the lock") |
91 | | -# self._owner = None |
92 | | -# # Remove from waiters if present |
93 | | -# if thread_info in self._waiters: |
94 | | -# self._waiters.remove(thread_info) |
95 | | -# if self._waiters: |
96 | | -# self._debug_logger.info( |
97 | | -# f": NEXT: {len(self._waiters)} threads still waiting: {self._waiters}" |
98 | | -# ) |
99 | | -# self._lock.release() |
100 | | - |
101 | | -# def __enter__(self): |
102 | | -# self.acquire() |
103 | | -# return self |
104 | | - |
105 | | -# def __exit__(self, exc_type, exc_val, exc_tb): |
106 | | -# self.release() |
| 34 | +class DebugLock: |
| 35 | + """A wrapper around threading.Lock that provides detailed debugging for lock acquisition/release""" |
| 36 | + |
| 37 | + def __init__(self, name: str = "DebugLock"): |
| 38 | + self._lock = threading.Lock() |
| 39 | + self._name = name |
| 40 | + self._owner: Optional[str] = None |
| 41 | + self._waiters: List[str] = [] |
| 42 | + self._debug_logger = logging.getLogger(f"{__name__}.{name}") |
| 43 | + # Ensure debug logging is visible |
| 44 | + if not self._debug_logger.handlers: |
| 45 | + handler = logging.StreamHandler() |
| 46 | + formatter = logging.Formatter( |
| 47 | + ":lock: %(asctime)s [%(threadName)s-%(thread)d] LOCK-%(name)s: %(message)s" |
| 48 | + ) |
| 49 | + handler.setFormatter(formatter) |
| 50 | + self._debug_logger.addHandler(handler) |
| 51 | + self._debug_logger.setLevel(logging.DEBUG) |
| 52 | + |
| 53 | + def acquire(self, blocking=True, timeout=-1): |
| 54 | + current = threading.current_thread() |
| 55 | + thread_info = f"{current.name}-{current.ident}" |
| 56 | + if self._owner: |
| 57 | + self._debug_logger.warning( |
| 58 | + f": WAITING: {thread_info} waiting for lock held by {self._owner}" |
| 59 | + ) |
| 60 | + self._waiters.append(thread_info) |
| 61 | + else: |
| 62 | + self._debug_logger.debug( |
| 63 | + f": TRYING: {thread_info} attempting to acquire lock" |
| 64 | + ) |
| 65 | + # Try to acquire the lock |
| 66 | + acquired = self._lock.acquire(blocking, timeout) |
| 67 | + if acquired: |
| 68 | + self._owner = thread_info |
| 69 | + self._debug_logger.info(f": ACQUIRED: {thread_info} got the lock") |
| 70 | + if self._waiters: |
| 71 | + self._debug_logger.info( |
| 72 | + f": WAITERS: {len(self._waiters)} threads waiting: {self._waiters}" |
| 73 | + ) |
| 74 | + else: |
| 75 | + self._debug_logger.error( |
| 76 | + f": FAILED: {thread_info} failed to acquire lock (timeout)" |
| 77 | + ) |
| 78 | + if thread_info in self._waiters: |
| 79 | + self._waiters.remove(thread_info) |
| 80 | + return acquired |
| 81 | + |
| 82 | + def release(self): |
| 83 | + current = threading.current_thread() |
| 84 | + thread_info = f"{current.name}-{current.ident}" |
| 85 | + if self._owner != thread_info: |
| 86 | + self._debug_logger.error( |
| 87 | + f": ERROR: {thread_info} trying to release lock owned by {self._owner}" |
| 88 | + ) |
| 89 | + else: |
| 90 | + self._debug_logger.info(f": RELEASED: {thread_info} released the lock") |
| 91 | + self._owner = None |
| 92 | + # Remove from waiters if present |
| 93 | + if thread_info in self._waiters: |
| 94 | + self._waiters.remove(thread_info) |
| 95 | + if self._waiters: |
| 96 | + self._debug_logger.info( |
| 97 | + f": NEXT: {len(self._waiters)} threads still waiting: {self._waiters}" |
| 98 | + ) |
| 99 | + self._lock.release() |
| 100 | + |
| 101 | + def __enter__(self): |
| 102 | + self.acquire() |
| 103 | + return self |
| 104 | + |
| 105 | + def __exit__(self, exc_type, exc_val, exc_tb): |
| 106 | + self.release() |
107 | 107 |
|
108 | 108 |
|
109 | 109 | class TelemetryHelper: |
@@ -430,10 +430,10 @@ class TelemetryClientFactory: |
430 | 430 | ] = {} # Map of session_id_hex -> BaseTelemetryClient |
431 | 431 | _executor: Optional[ThreadPoolExecutor] = None |
432 | 432 | _initialized: bool = False |
433 | | - _lock = threading.Lock() # Thread safety for factory operations |
434 | | - # _lock = DebugLock( |
435 | | - # "TelemetryClientFactory" |
436 | | - # ) # Thread safety for factory operations with debugging |
| 433 | + # _lock = threading.Lock() # Thread safety for factory operations |
| 434 | + _lock = DebugLock( |
| 435 | + "TelemetryClientFactory" |
| 436 | + ) # Thread safety for factory operations with debugging |
437 | 437 | _original_excepthook = None |
438 | 438 | _excepthook_installed = False |
439 | 439 |
|
|
0 commit comments