New submission from Yevhenii Hyzyla <hyz...@gmail.com>:

Class `asyncio.Semaphore` has dequeue in implementation for waiters of 
semaphore and seems like the intention of this dequeue is to maintain FIFO 
queue of waiters. But it doesn't work, coroutine that releases semaphore can 
acquire semaphore again. Below is reproducible example:

```python
import asyncio


async def process(idx: int, semaphore: asyncio.Semaphore) -> None:
    while True:
        async with semaphore:
            print(f'ACQUIRE {idx}')
            await asyncio.sleep(1)


async def main() -> None:
    semaphore = asyncio.Semaphore(5)
    await asyncio.gather(*[process(idx, semaphore) for idx in range(20)])

asyncio.run(main())
```

In console:
```
/home/y.hyzyla/Work/asynciosemaphorebug/venv/bin/python 
/home/y.hyzyla/Work/asynciosemaphorebug/main.py
ACQUIRE 0
ACQUIRE 1
ACQUIRE 2
ACQUIRE 3
ACQUIRE 4
ACQUIRE 0
ACQUIRE 1
ACQUIRE 2
ACQUIRE 3
ACQUIRE 4
ACQUIRE 0
ACQUIRE 1
ACQUIRE 2
ACQUIRE 3
ACQUIRE 4
....
```

Ugly fix, is to add asyncio.sleep right before semaphore.
```python
    while True:
        await asyncio.sleep(0)
        async with semaphore:
            ...
```

Also, I found a comment on Stack Overflow about race condition in Semaphore 
implementation, but I don't know about the quality of that comment:

https://stackoverflow.com/questions/55951233/does-pythons-asyncio-lock-acquire-maintain-order#comment112978366_55951304

----------
components: asyncio
messages: 407809
nosy: asvetlov, hyzyla, yselivanov
priority: normal
severity: normal
status: open
title: asyncio.Semaphore waiters deqeueu doesn't work
versions: Python 3.8

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue45997>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to