Fix connect timeout not accounting for DNS resolution time#810
Fix connect timeout not accounting for DNS resolution time#810
Conversation
The ConnectTimeout function previously only applied the timeout to the TCP connect phase (poll/select), but DNS resolution via getaddrinfo() had no timeout applied. On platforms like Android with no network, getaddrinfo() can block for 30-40 seconds, making user-set connect_timeout and timeout values ineffective. Changes: - ConnectTimeout now tracks elapsed time for DNS resolution and subtracts it from the TCP connect timeout. If DNS takes longer than the timeout, it returns ETIMEDOUT immediately. - http_client_connect adjusts SSL handshake timeout by subtracting time already spent on DNS+TCP connect. - http_client_exec checks overall request timeout after connect, handling cases where connect took longer than expected. - Updated build files (CMakeLists.txt, Makefile) to link htime.c with all targets that use hsocket.c. Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com>
…ly on SSL timeout Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR tightens timeout accounting for TCP connect + TLS handshake in the synchronous HTTP client and updates unit-test build rules to link the time utilities now required by hsocket.c.
Changes:
- Track elapsed time across
ConnectTimeout()and apply the remaining budget to the TLS handshake socket receive timeout. - Update
ConnectTimeout()to subtract time spent in initial connect setup from the poll/select wait budget. - Fix unit-test build targets (CMake + Makefile) to link
base/htime.cwherebase/hsocket.cis compiled directly.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
unittest/CMakeLists.txt |
Adds ../base/htime.c to several unittest executables that compile hsocket.c directly. |
Makefile |
Adds base/htime.c to additional unittest build commands that include base/hsocket.c. |
http/client/HttpClient.cpp |
Accounts for connect time when budgeting TLS handshake receive timeout; adds an extra overall-timeout check after connect. |
base/hsocket.c |
Makes ConnectTimeout() time-aware by subtracting setup time before waiting for connect completion. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
http/client/HttpClient.cpp
Outdated
| if (timeout_ms > 0) { | ||
| cur_time = gettick_ms(); | ||
| if (cur_time - start_time >= timeout_ms) { | ||
| cli->Close(); | ||
| return ERR_TASK_TIMEOUT; |
There was a problem hiding this comment.
The post-connect timeout check duplicates the existing CHECK_TIMEOUT logic and introduces a second timeout-handling codepath (direct return vs goto timeout). Consider reusing CHECK_TIMEOUT here to keep timeout behavior consistent and avoid future divergence (e.g., if cleanup logic changes).
| add_executable(ftp ftp_test.c ../protocol/ftp.c ../base/hsocket.c ../base/htime.c) | ||
| target_include_directories(ftp PRIVATE .. ../base ../protocol) | ||
|
|
||
| add_executable(sendmail sendmail_test.c ../protocol/smtp.c ../base/hsocket.c ../util/base64.c) | ||
| add_executable(sendmail sendmail_test.c ../protocol/smtp.c ../base/hsocket.c ../base/htime.c ../util/base64.c) | ||
| target_include_directories(sendmail PRIVATE .. ../base ../protocol ../util) |
There was a problem hiding this comment.
nslookup links only nslookup_test.c and dns.c, but dns.c calls WSAInit() under OS_WIN, which is implemented in base/hsocket.c. This target will fail to link on Windows. Consider adding ../base/hsocket.c (and ../base/htime.c, since hsocket.c now depends on gettick_ms) to the nslookup executable sources to keep CMake parity with the Makefile unittest build.
|
@copilot apply changes based on the comments in this thread |
… target - Replace inline timeout check with CHECK_TIMEOUT macro by moving variable declarations before the connect: label to avoid crossing initializations with goto. - Add hsocket.c and htime.c to nslookup CMake target for Windows link compatibility (dns.c calls WSAInit from hsocket.c). Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com>
Applied both review changes in 899eb0d:
|
base/hsocket.c
Outdated
| unsigned int elapsed = gettick_ms() - start_time; | ||
| int remaining = ms - (int)elapsed; | ||
| if (remaining <= 0) { | ||
| errno = ETIMEDOUT; |
…ETIMEDOUT When DNS resolution exhausts the timeout budget, explicitly close the socket with closesocket() and return -ETIMEDOUT directly, instead of relying on socket_errno_negative() which reads errno indirectly and could return the wrong error code on Windows. Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com>
ConnectTimeoutinbase/hsocket.cto account for DNS resolution time in the connect timeouthttp_client_connectinhttp/client/HttpClient.cppto track elapsed time for SSL handshake timeouthttp_client_execinhttp/client/HttpClient.cppto add timeout check after connect callhtime.cwith all targets usinghsocket.cCHECK_TIMEOUTmacro instead of inline duplicatehsocket.candhtime.ctonslookupCMake targetclosesocket(connfd)before returning-ETIMEDOUTinConnectTimeoutOriginal prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.