Skip to content

Fix operator precedence on evicted-session close timeout#3832

Open
genisis0x wants to merge 3 commits intoApeWorX:mainfrom
genisis0x:fix/evicted-session-timeout-precedence
Open

Fix operator precedence on evicted-session close timeout#3832
genisis0x wants to merge 3 commits intoApeWorX:mainfrom
genisis0x:fix/evicted-session-timeout-precedence

Conversation

@genisis0x
Copy link
Copy Markdown

What was wrong?

HTTPSessionManager.cache_and_return_session (sync) and async_cache_and_return_session (async) schedule a close-evicted-sessions task to fire after the in-flight request would have timed out, plus a small 0.1s slack so any request that started right before the eviction has time to finish before the underlying session is closed.

Both call sites used:

# sync, web3/_utils/http_session_manager.py:99
request_timeout or DEFAULT_HTTP_TIMEOUT + 0.1
# async, web3/_utils/http_session_manager.py:271
request_timeout.total or DEFAULT_HTTP_TIMEOUT + 0.1

+ binds tighter than or in Python, so the expression actually parses as request_timeout or (DEFAULT_HTTP_TIMEOUT + 0.1). The intended + 0.1 slack only applied when the caller fell back to the default. Any caller that supplied a non-default timeout (e.g. request_timeout=5) had its close timer fire at exactly 5.0s, racing the in-flight request:

>>> request_timeout = 5
>>> DEFAULT_HTTP_TIMEOUT = 30
>>> request_timeout or DEFAULT_HTTP_TIMEOUT + 0.1
5
>>> (request_timeout or DEFAULT_HTTP_TIMEOUT) + 0.1
5.1

The comments above each call site already describe the intended behavior (wait over the default timeout / bit more than the request_timeout).

How was it fixed?

Parenthesize the or so the slack is always applied to the chosen timeout:

(request_timeout or DEFAULT_HTTP_TIMEOUT) + 0.1

Same change in both the sync and async paths.

Cute Animal Picture

cat

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Test plan

Added focused regression tests in tests/core/utilities/test_http_session_manager.py:

  • test_session_manager_evicted_close_timer_uses_request_timeout_plus_slack — patches threading.Timer, fills a 1-entry cache, and asserts the captured interval is request_timeout + 0.1.
  • test_session_manager_evicted_close_timer_falls_back_to_default — same path with request_timeout=None, asserts the interval is DEFAULT_HTTP_TIMEOUT + 0.1.
  • test_async_evicted_close_task_uses_request_timeout_plus_slack — async equivalent that patches _async_close_evicted_sessions and asserts it was scheduled with ClientTimeout.total + 0.1.

The pre-existing test_async_session_manager_cache_does_not_close_session_before_call already exercised the async eviction path and continues to pass with the change (it waited for _timeout + 0.1 regardless and is not sensitive to the bug).

genisis0x added 3 commits May 1, 2026 16:47
`HTTPSessionManager.cache_and_return_session` schedules
`_close_evicted_sessions` (sync) and `_async_close_evicted_sessions`
(async) to fire after the in-flight request would time out, plus a
small `0.1`s slack so any request that started right before the
eviction has time to finish.

Both call sites used:

    request_timeout or DEFAULT_HTTP_TIMEOUT + 0.1

Python parses `+` tighter than `or`, so this is `request_timeout or
(DEFAULT_HTTP_TIMEOUT + 0.1)`. When a caller supplied a non-default
timeout (e.g. 5s), the close timer fired at exactly the request
timeout instead of `request_timeout + 0.1`, and the evicted session
could be closed out from under an in-flight request. The intended
slack only kicked in when the caller relied on the default.

Parenthesize the expression so the `+ 0.1` slack is always applied:

    (request_timeout or DEFAULT_HTTP_TIMEOUT) + 0.1

Adds focused regression tests for both sync and async paths that
patch the timer / scheduling primitive and assert the captured
interval is `request_timeout + 0.1`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant