concurrent.interpreters.Queue.get()/put() mishandle the timeout argument
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Python
- Estrellas
- 77.2k
- Forks
- 35.9k
- Métricas de merge de PR
- Métricas de PR pendientes
Descripción
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
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con concurrent.interpreters.Queue.get() y Queue.put(), y luego compara su gestión de timeouts con queue.Queue, tal como se describe en el issue. Confirma el comportamiento para timeouts fraccionarios, negativos y NaN, y para los ajustes del reloj; se considera completado cuando se conservan las esperas fraccionarias, se genera ValueError donde se especifica y se utiliza una deadline monotónica. Inspecciona los PRs enlazados antes de empezar, porque ya hay trabajo en curso.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- python
- Área
- backend
- Tipo de issue
- Error
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Estado de actividad
- Estancado
- Claridad
- Bien especificado
- Aptitud para principiantes
- 25/100