Fix verify() stalling until expiry after a select() timeout#211
Open
djw8605 wants to merge 1 commit into
Open
Conversation
The synchronous verify() loop only called verify_async_continue() when select() reported I/O activity (select_result > 0). select() clears the fd_sets on timeout, and the sets are only repopulated inside curl_multi_fdset() via verify_async_continue(), so after the first 50ms period with no socket activity the loop kept selecting on empty fd_sets and never drove libcurl again, spinning until expiry_time and failing with 'Timeout when loading the OIDC metadata'. libcurl also requires curl_multi_perform() to be called after a select() timeout so it can run its internal (non-socket) work such as DNS retries and connection timeouts. Continue on select_result >= 0 so timeouts drive the transfer forward. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The synchronous
verify()loop insrc/scitokens_internal.honly callsverify_async_continue()whenselect()reports I/O activity (select_result > 0).select()is value-result: on a timeout it clears the fd_sets, and the sets are only repopulated bycurl_multi_fdset()insideperform_continue()— which is only reachable throughverify_async_continue(). So the first time the issuer takes more than 50 ms to produce socket activity (slow response, DNS resolution, curl internal retry timers, ormax_fd == -1during connection setup), the loop keeps selecting on empty fd_sets, never drives libcurl again, and fails with "Timeout when loading the OIDC metadata" after the fullexpiry_timedeadline (20 s for the enforcer paths).libcurl's documentation also explicitly requires calling
curl_multi_perform()after aselect()timeout so it can run internal non-socket work (DNS retries, connect timeouts, timers).This was a regression introduced in commit cb1463f (monitoring API, #182), which replaced an unconditional
verify_async_continue()call with theselect_result > 0condition.Impact
Every
enforcer_test/enforcer_generate_acls/validator_validatecall that triggers a key fetch or refresh (everynext_updateinterval, default 600 s) hangs for the full 20 s deadline and then fails whenever the issuer doesn't respond within 50 ms — i.e., essentially any real-world WAN latency.Fix
Continue on
select_result >= 0so timeouts drive the transfer forward; only-1(signal/interrupt) skips the continue call.Testing
ctestunit, env_config, and monitoring suites pass.🤖 Generated with Claude Code