Skip to content

Conversation

@vszakats
Copy link
Member

@vszakats vszakats commented Dec 13, 2025

  • add local API toolx_localtime() to wrap the banned function
    localtime(). Used from libcurl, libtests and test servers.
  • auto-detect and use localtime_r() where available (e.g. Linux).
    Also to support multi-threading.
  • use localtime_s() on Windows. It requires MSVC or mingw-w64 v4+.
    Also to support multi-threading.
    Use local workaround to also support mingw-w64 v3.
  • add src/toolx to keep internal APIs used by the curl tool and tests,
    but not by libcurl. toolx_localtime() is the first API in it.
  • replace localtime() calls with toolx_localtime().
    Except in examples.
  • note Windows XP's default msvcrt.dll doesn't offer secure CRT APIs.
    XP likely needs a newer version of this DLL, or may not run.
  • note that localtime() mirrors gmtime(), with the difference that
    gmtime()'s internal wrapper lives in curlx.

Also:

  • drop redundant int casts.

Refs:
https://learn.microsoft.com/cpp/c-runtime-library/reference/localtime-localtime32-localtime64
https://learn.microsoft.com/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s
https://pubs.opengroup.org/onlinepubs/9799919799/functions/localtime.html
https://linux.die.net/man/3/localtime_r

Ref: #19955 (for gmtime_r())
Follow-up to 54d9f06


@vszakats
Copy link
Member Author

vszakats commented Dec 13, 2025

Test 3207 flaky failure in mingw, AM x86_64 c-ares U:
https://github.com/curl/curl/actions/runs/20186607715/job/57957786919?pr=19957

@bagder
Copy link
Member

bagder commented Dec 13, 2025

Isn't the only use of localtime in src/tool_cb_dbg.c ? Why add it to libcurl at all?

@vszakats
Copy link
Member Author

Isn't the only use of localtime in src/tool_cb_dbg.c ? Why add it to libcurl at all?

It's also used from libtests (and servers) to get the time for debug logs.

@bagder
Copy link
Member

bagder commented Dec 13, 2025

I still object to adding anything to libcurl that isn't used by libcurl.

@vszakats
Copy link
Member Author

I don't completely get the point of this rule, but more importantly how to solve this then? Maintain 3 copies of this function doesn't look practical.

Or maybe make it a macro and put it in curl_setup.h?

Or add to a separate curlx c file that's excluded from libcurl?

Or add a guard to exclude it while building libcurl?

@bagder
Copy link
Member

bagder commented Dec 14, 2025

The rule is there to keep the crown jewel as slim as it can be and not add stuff that isn't used. For size, for complexity and more.

The tool and the tests don't need threadsafe localtime versions to begin with - at least not for as long as we don't use threads in the tool.

Or maybe make it a macro and put it in curl_setup.h?
Or add to a separate curlx c file that's excluded from libcurl?
Or add a guard to exclude it while building libcurl?

Neither I think. Because in my mind, anything that adds anything in lib/ is wrong if that code is not also used by code in lib/.

We could potentially create a curlt (name just a suggestion) set of functions that are written for the tool but can be re-used by the tests.

@vszakats
Copy link
Member Author

vszakats commented Dec 14, 2025

The rule is there to keep the crown jewel as slim as it can be and not add stuff that isn't used. For size, for complexity and more.

ACK.

The tool and the tests don't need threadsafe localtime versions to begin with - at least not for as long as we don't use threads in the tool.

Or maybe make it a macro and put it in curl_setup.h?
Or add to a separate curlx c file that's excluded from libcurl?
Or add a guard to exclude it while building libcurl?

Neither I think. Because in my mind, anything that adds anything in lib/ is wrong if that code is not also used by code in lib/.

We could potentially create a curlt (name just a suggestion) set of functions that are written for the tool but can be re-used by the tests.

On the other hand localtime is a banned function, yet it's used from places,
and it's unlikely to go away. It's also deprecated by MSVC. (It's also an exact
mirror of gmtime, with identical issues/properties.) So I figure it'd be nice
to fix, and fix in one place, then forget.

How does src/toolx sound?

@bagder
Copy link
Member

bagder commented Dec 14, 2025

How does src/toolx sound?

Perfect!

@vszakats vszakats marked this pull request as ready for review December 14, 2025 15:31
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a thread-safe wrapper for the localtime() function by creating a new internal API toolx_localtime() in a new src/toolx directory. The wrapper automatically detects and uses thread-safe alternatives: localtime_r() on Unix-like systems and localtime_s() on Windows (with special handling for mingw-w64 v3). All occurrences of localtime() in the curl tool, test servers, and test libraries have been replaced with this new wrapper to improve thread-safety across the codebase.

  • Introduces toolx_localtime() as a portable, thread-safe replacement for localtime()
  • Creates new src/toolx directory for tool-internal APIs shared between curl tool and tests
  • Updates build systems (Autotools, CMake, Windows projects) to include the new toolx module and detect localtime_r availability

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/toolx/tool_time.h New header defining the toolx_localtime() API
src/toolx/tool_time.c Implementation using platform-specific thread-safe localtime variants
src/tool_cb_dbg.c Replaces localtime() with toolx_localtime() in debug callback
tests/server/util.c Converts logging to use thread-safe toolx_localtime()
tests/libtest/testtrace.c Updates test tracing to use toolx_localtime()
tests/server/Makefile.inc Adds TOOLX_C variable for new toolx sources
tests/server/Makefile.am Includes toolx headers and sources in build
tests/server/CMakeLists.txt Updates CMake to build with toolx
tests/libtest/Makefile.inc Adds TOOLX_C for libtest builds
tests/libtest/Makefile.am Integrates toolx into libtest build
tests/libtest/CMakeLists.txt Updates CMake for toolx integration
src/Makefile.inc Adds toolx sources and headers to curl build
projects/generate.bat Adds toolx file generation for Windows projects
projects/Windows/tmpl/curl.vcxproj Includes toolx in Visual Studio project template
m4/curl-functions.m4 Adds autoconf macro to detect localtime_r availability
configure.ac Invokes CURL_CHECK_FUNC_LOCALTIME_R during configuration
CMakeLists.txt Adds check for localtime_r symbol
lib/curl_config.h.cmake Defines HAVE_LOCALTIME_R configuration
lib/config-plan9.h Enables HAVE_LOCALTIME_R for Plan 9
lib/config-os400.h Enables HAVE_LOCALTIME_R for OS/400
CMake/win32-cache.cmake Sets HAVE_LOCALTIME_R=0 for Windows
CMake/unix-cache.cmake Sets HAVE_LOCALTIME_R=1 for Unix
lib/curl_setup.h Updates comment to reflect localtime() is no longer used in tests

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

to silence AIs, and avoid unnecessary/misleading variations of this code.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

vszakats added a commit that referenced this pull request Dec 16, 2025
Move `Curl_gmtime()` to curlx and rename to `curlx_gmtime()`. Then call
the internal wrapper also from the curl tool, to avoid using the banned
`gmtime()` directly, and using better, thread-safe alternatives when
available.

Windows `gmtime_s()` requires mingw-w64 v4+ or MSVC. Use local
workaround to also support mingw-w64 v3. `gmtime_s()` also makes
defining `_CRT_SECURE_NO_WARNINGS` unnecessary.

Also:
- lib: drop unused `parsedate.h` includes.
- drop redundant cast from `gmtime_r()` result.
- autotools: reverse condition in the proto detection to avoid
  misleading readers. (the condition plays no role in detection.)
- note Windows XP's default `msvcrt.dll` doesn't offer secure CRT APIs.
  XP likely needs a newer version of this DLL, or may not run.

Refs:
https://learn.microsoft.com/cpp/c-runtime-library/reference/gmtime-gmtime32-gmtime64
https://learn.microsoft.com/cpp/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s
https://pubs.opengroup.org/onlinepubs/9799919799/functions/gmtime.html
https://linux.die.net/man/3/gmtime_r

Ref: #19957 (for `localtime_r()`)
Follow-up to 54d9f06
Closes #19955
@vszakats vszakats closed this in 32454b9 Dec 16, 2025
@vszakats vszakats deleted the localtime branch December 16, 2025 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants