Skip to content

Commit ec2c519

Browse files
fix: avoid acquire_sync deadlock under running event loop
Agent-Logs-Url: https://github.com/MervinPraison/PraisonAI/sessions/c9e7c913-a80d-474a-bd5d-731c129ad614 Co-authored-by: MervinPraison <454862+MervinPraison@users.noreply.github.com>
1 parent e9d8602 commit ec2c519

2 files changed

Lines changed: 16 additions & 12 deletions

File tree

src/praisonai-agents/praisonaiagents/agent/concurrency.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,19 @@ async def acquire(self, agent_name: str) -> None:
8686
def acquire_sync(self, agent_name: str) -> None:
8787
"""Synchronous acquire — for non-async code paths.
8888
89-
Uses a proper sync-to-async bridge to avoid private attribute manipulation.
9089
Prefer async acquire() when possible.
9190
"""
9291
sem = self._get_semaphore(agent_name)
9392
if sem is None:
9493
return
9594
try:
9695
asyncio.get_running_loop()
97-
# We're inside an async loop — cannot block. Run acquire in a thread
98-
# with its own loop to go through the semaphore's proper acquire path.
99-
import concurrent.futures
100-
def _acquire_in_new_loop():
101-
loop = asyncio.new_event_loop()
102-
try:
103-
loop.run_until_complete(sem.acquire())
104-
finally:
105-
loop.close()
106-
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
107-
pool.submit(_acquire_in_new_loop).result(timeout=30)
96+
# Running loop in current thread: blocking here can deadlock.
97+
logger.warning(
98+
f"acquire_sync('{agent_name}') called with a running event loop; "
99+
"use async acquire() in async contexts."
100+
)
101+
return
108102
except RuntimeError:
109103
# No running loop — safe to create one
110104
loop = asyncio.new_event_loop()

src/praisonai-agents/tests/unit/agent/test_agent_concurrency.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,13 @@ def test_sync_acquire_release(self):
106106
# Sync acquire should work
107107
reg.acquire_sync("sync_agent")
108108
reg.release("sync_agent")
109+
110+
@pytest.mark.asyncio
111+
async def test_sync_acquire_running_loop_noop(self):
112+
"""Sync acquire in async context should not block event loop."""
113+
from praisonaiagents.agent.concurrency import ConcurrencyRegistry
114+
reg = ConcurrencyRegistry()
115+
reg.set_limit("loop_agent", 1)
116+
await reg.acquire("loop_agent")
117+
reg.acquire_sync("loop_agent")
118+
reg.release("loop_agent")

0 commit comments

Comments
 (0)