mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-20 16:08:51 +03:00
8ff73e961a
* treat Semaphore._waiters as length zero when it is None We access the `._waiters` private attribute of the Python asyncio `Semaphore` class. This was changed in Python 3.10.8 (and other versions) to be initialized to `None` instead of an empty deque. Our existing unconditional length checks failed on the new `None` default. This seems to block syncing. https://github.com/python/cpython/pull/97020 https://github.com/python/cpython/compare/v3.10.7..v3.10.8#diff-0fee1befb15023abc0dad2623effa93a304946796929f6cb445d11a57821e737 Reported traceback: ```python-traceback 2022-10-12T20:03:59.367 full_node full_node_server : INFO Connected with full_node {'host': '65.34.144.6', 'port': 8444} 2022-10-12T20:03:59.370 full_node full_node_server : ERROR Exception: object of type 'NoneType' has no len(), {'host': '65.34.144.6', 'port': 8444}. Traceback (most recent call last): File "/home/summa/chia-blockchain/chia/server/server.py", line 598, in wrapped_coroutine result = await coroutine File "/home/summa/chia-blockchain/chia/full_node/full_node_api.py", line 114, in new_peak waiter_count = len(self.full_node.new_peak_sem._waiters) TypeError: object of type 'NoneType' has no len() 2022-10-12T20:03:59.371 full_node full_node_server : ERROR Exception: object of type 'NoneType' has no len() <class 'TypeError'>, closing connection {'host': '65.34.144.6', 'port': 8444}. Traceback (most recent call last): File "/home/summa/chia-blockchain/chia/server/server.py", line 608, in api_call response: Optional[Message] = await asyncio.wait_for(wrapped_coroutine(), timeout=timeout) File "/usr/lib/python3.10/asyncio/tasks.py", line 408, in wait_for return await fut File "/home/summa/chia-blockchain/chia/server/server.py", line 605, in wrapped_coroutine raise e File "/home/summa/chia-blockchain/chia/server/server.py", line 598, in wrapped_coroutine result = await coroutine File "/home/summa/chia-blockchain/chia/full_node/full_node_api.py", line 114, in new_peak waiter_count = len(self.full_node.new_peak_sem._waiters) TypeError: object of type 'NoneType' has no len() 2022-10-12T20:03:59.487 full_node full_node_server : INFO Connection closed: 65.34.144.6, node id: 506fe4c05ce6b72bb707471842e552307c7a547aa9ba981175db5c08fa3e47e6 ``` * add LimitedSemaphore
40 lines
1013 B
Python
40 lines
1013 B
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import contextlib
|
|
from dataclasses import dataclass
|
|
from typing import AsyncIterator
|
|
|
|
from typing_extensions import final
|
|
|
|
|
|
class LimitedSemaphoreFullError(Exception):
|
|
def __init__(self) -> None:
|
|
super().__init__("no waiting slot available")
|
|
|
|
|
|
@final
|
|
@dataclass
|
|
class LimitedSemaphore:
|
|
_semaphore: asyncio.Semaphore
|
|
_available_count: int
|
|
|
|
@classmethod
|
|
def create(cls, active_limit: int, waiting_limit: int) -> LimitedSemaphore:
|
|
return cls(
|
|
_semaphore=asyncio.Semaphore(active_limit),
|
|
_available_count=active_limit + waiting_limit,
|
|
)
|
|
|
|
@contextlib.asynccontextmanager
|
|
async def acquire(self) -> AsyncIterator[int]:
|
|
if self._available_count < 1:
|
|
raise LimitedSemaphoreFullError()
|
|
|
|
self._available_count -= 1
|
|
try:
|
|
async with self._semaphore:
|
|
yield self._available_count
|
|
finally:
|
|
self._available_count += 1
|