concurrent.interpreters.Queue.get()/put() mishandle the timeout argument
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 77.2k
- Forks
- 35.9k
- PR merge metrics
- PR metrics pending
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with concurrent.interpreters.Queue.get() and Queue.put(), then compare their timeout handling with queue.Queue as described in the issue. Confirm the behavior for fractional, negative, and NaN timeouts and for clock adjustments; done means preserving fractional waits, raising ValueError where specified, and using a monotonic deadline. Inspect the linked PRs before starting because work is already underway.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100