python / python/cpython

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

Đang mở
#153,005 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

stdlib topic-subinterpreters type-bug
Ngôn ngữ chính
Python
Star
77.2k
Fork
35.9k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

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

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với concurrent.interpreters.Queue.get() và Queue.put(), sau đó so sánh cách xử lý timeout của chúng với queue.Queue như được mô tả trong issue. Xác nhận hành vi đối với các timeout dạng phân số, âm và NaN, cũng như đối với việc điều chỉnh đồng hồ; hoàn tất nghĩa là vẫn giữ nguyên thời gian chờ dạng phân số, phát sinh ValueError ở nơi được chỉ định và sử dụng deadline đơn điệu. Kiểm tra các PR được liên kết trước khi bắt đầu vì công việc đã được tiến hành.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
backend
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
25/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.