python / python/cpython

concurrent.interpreters.Queue.get()/put() mishandle the timeout argument

Abierto
#153,005 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

stdlib topic-subinterpreters type-bug
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.

  1. 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.9 waits for only about one second.
    queue.Queue, which this queue is meant to be compatible with, accepts a
    floating-point number of seconds.

  2. Because of the same int() conversion, a small negative float such as
    timeout=-0.5 is truncated to 0 and passes the timeout < 0 check
    instead of raising ValueError.

  3. The deadline is computed with time.time() (the wall clock), while
    queue.Queue uses time.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

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. 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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.