concurrent.interpreters.Queue.get()/put() mishandle the timeout argument
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 77.2k
- Forks
- 35.9k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
concurrent.interpreters.Queue.get() and Queue.put() mishandle their
timeout argument in three related ways.
-
The value is converted with
int(timeout), which truncates a floating-point
timeout to whole seconds. A timeout in the interval[0, 1)becomes a
non-blocking call, and e.g.timeout=1.9waits for only about one second.
queue.Queue, which this queue is meant to be compatible with, accepts a
floating-point number of seconds. -
Because of the same
int()conversion, a small negative float such as
timeout=-0.5is truncated to0and passes thetimeout < 0check
instead of raisingValueError. -
The deadline is computed with
time.time()(the wall clock), while
queue.Queueusestime.monotonic(). The timeout can therefore over- or
under-wait if the system clock is adjusted (NTP step, manual change) during
the call.
Reproducer (3.14.5)
import time
from concurrent.interpreters import create_queue
q = create_queue(maxsize=1)
q.put(b"x") # fill it
start = time.perf_counter()
try:
q.put(b"y", timeout=0.5) # expected: block ~0.5s, then QueueFull
except Exception as exc:
print(type(exc).__name__, f"{(time.perf_counter() - start) * 1000:.1f} ms")
# -> QueueFull 0.0 ms (expected ~500 ms)
q2 = create_queue()
start = time.perf_counter()
try:
q2.get(timeout=0.9) # expected: block ~0.9s, then QueueEmpty
except Exception as exc:
print(type(exc).__name__, f"{(time.perf_counter() - start) * 1000:.1f} ms")
# -> QueueEmpty 0.0 ms (expected ~900 ms)
For comparison, queue.Queue().get(timeout=0.5) blocks for about 500 ms.
The fix is to use the timeout value as given, reject a negative or NaN timeout
with ValueError, and base the deadline on time.monotonic().
Linked PRs
- gh-153006
- gh-154156
- gh-155967
- gh-156018
- gh-156019
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit concurrent.interpreters.Queue.get() und Queue.put() und vergleiche anschließend deren Timeout-Behandlung mit queue.Queue, wie im Issue beschrieben. Bestätige das Verhalten für fraktionale, negative und NaN-Timeouts sowie bei Uhranpassungen; als erledigt gilt, dass fraktionale Wartezeiten erhalten bleiben, an den angegebenen Stellen ValueError ausgelöst wird und eine monotone Deadline verwendet wird. Sieh dir die verknüpften PRs an, bevor du beginnst, da bereits daran gearbeitet wird.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- backend
- Issue-Typ
- Bug
- Schwierigkeit
- 3/5
- Geschätzter Aufwand
- 1-2 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 25/100