]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
windows: replace `_beginthreadex()` with `CreateThread()`
authorViktor Szakats <commit@vsz.me>
Fri, 1 Aug 2025 19:09:52 +0000 (21:09 +0200)
committerViktor Szakats <commit@vsz.me>
Fri, 19 Sep 2025 23:28:35 +0000 (01:28 +0200)
Replace `_beginthreadex()` C runtime calls with native win32 API
`CreateThread()`. The latter was already used in `src/tool_doswin.c`
and in UWP and Windows CE builds before this patch. After this patch
all Windows flavors use it. To drop PP logic and simplify code.

While working on this it turned out that `src/tool_doswin.c` calls
`TerminateThread()`, which isn't recommended by the documentation,
except for "the most extreme cases". This patch makes no attempt
to change that code.
Ref: 9a2663322c330ff11275abafd612e9c99407a94a #17572
Ref: https://learn.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread

Also:
- use `WaitForSingleObjectEx()` on all desktop Windows.
  Ref: 4be80d5109a340973dc6ce0221ec5c5761587df0
  Ref: https://sourceforge.net/p/curl/feature-requests/82/
  Ref: https://learn.microsoft.com/windows/win32/api/synchapi/nf-synchapi-waitforsingleobjectex
- tests: drop redundant casts.
- lib3207: fix to not rely on thread macros when building without thread
  support.

Assisted-by: Jay Satiro
Assisted-by: Marcel Raad
Assisted-by: MichaƂ Petryka
Follow-up to 38029101e2d78ba125732b3bab6ec267b80a0e72 #11625

Closes #18451

lib/curl_threads.c
lib/curl_threads.h
tests/libtest/lib3026.c
tests/libtest/lib3207.c
tests/server/sockfilt.c
tests/server/util.c

index 96fd0f8a7af9d7699833215e3353cfdf1a944fcd..94425d19fe8a9bb2d53b9136fd54f18ad4ddef86 100644 (file)
 
 #include <curl/curl.h>
 
-#ifdef USE_THREADS_POSIX
-#  ifdef HAVE_PTHREAD_H
-#    include <pthread.h>
-#  endif
-#elif defined(USE_THREADS_WIN32)
-#  include <process.h>
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+#include <pthread.h>
 #endif
 
 #include "curl_threads.h"
@@ -105,20 +101,8 @@ int Curl_thread_join(curl_thread_t *hnd)
 curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T
                                  (CURL_STDCALL *func) (void *), void *arg)
 {
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
-  typedef HANDLE curl_win_thread_handle_t;
-#else
-  typedef uintptr_t curl_win_thread_handle_t;
-#endif
-  curl_thread_t t;
-  curl_win_thread_handle_t thread_handle;
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
-  thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL);
-#else
-  thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL);
-#endif
-  t = (curl_thread_t)thread_handle;
-  if((t == 0) || (t == LongToHandle(-1L))) {
+  curl_thread_t t = CreateThread(NULL, 0, func, arg, 0, NULL);
+  if(!t) {
 #ifdef UNDER_CE
     DWORD gle = GetLastError();
     /* !checksrc! disable ERRNOVAR 1 */
@@ -142,7 +126,7 @@ void Curl_thread_destroy(curl_thread_t *hnd)
 
 int Curl_thread_join(curl_thread_t *hnd)
 {
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+#ifdef UNDER_CE
   int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
 #else
   int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0);
index 82f08c5fbb566d8cb6349c06bd0b959047545f5c..241014cc6acb367512452a6dc37e56073bb4d9f6 100644 (file)
@@ -26,6 +26,7 @@
 #include "curl_setup.h"
 
 #ifdef USE_THREADS_POSIX
+#  define CURL_THREAD_RETURN_T   unsigned int
 #  define CURL_STDCALL
 #  define curl_mutex_t           pthread_mutex_t
 #  define curl_thread_t          pthread_t *
@@ -35,7 +36,8 @@
 #  define Curl_mutex_release(m)  pthread_mutex_unlock(m)
 #  define Curl_mutex_destroy(m)  pthread_mutex_destroy(m)
 #elif defined(USE_THREADS_WIN32)
-#  define CURL_STDCALL           __stdcall
+#  define CURL_THREAD_RETURN_T   DWORD
+#  define CURL_STDCALL           WINAPI
 #  define curl_mutex_t           CRITICAL_SECTION
 #  define curl_thread_t          HANDLE
 #  define curl_thread_t_null     (HANDLE)0
 #  define Curl_mutex_acquire(m)  EnterCriticalSection(m)
 #  define Curl_mutex_release(m)  LeaveCriticalSection(m)
 #  define Curl_mutex_destroy(m)  DeleteCriticalSection(m)
-#else
-#  define CURL_STDCALL
-#endif
-
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
-#define CURL_THREAD_RETURN_T DWORD
-#else
-#define CURL_THREAD_RETURN_T unsigned int
 #endif
 
 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
index 2b35a258417a7ce0262c14d1009bb2ff62aebc7e..167fdd4d332f4fb119386500bb292c9126e7e16c 100644 (file)
 #define NUM_THREADS 100
 
 #ifdef _WIN32
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
-static DWORD WINAPI t3026_run_thread(LPVOID ptr)
-#else
-#include <process.h>
-static unsigned int WINAPI t3026_run_thread(void *ptr)
-#endif
+static DWORD WINAPI t3026_run_thread(void *ptr)
 {
   CURLcode *result = ptr;
 
@@ -44,13 +39,8 @@ static unsigned int WINAPI t3026_run_thread(void *ptr)
 
 static CURLcode test_lib3026(const char *URL)
 {
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
-  typedef HANDLE curl_win_thread_handle_t;
-#else
-  typedef uintptr_t curl_win_thread_handle_t;
-#endif
   CURLcode results[NUM_THREADS];
-  curl_win_thread_handle_t thread_handles[NUM_THREADS];
+  HANDLE thread_handles[NUM_THREADS];
   unsigned tid_count = NUM_THREADS, i;
   CURLcode test_failure = CURLE_OK;
   curl_version_info_data *ver;
@@ -65,13 +55,9 @@ static CURLcode test_lib3026(const char *URL)
   }
 
   for(i = 0; i < tid_count; i++) {
-    curl_win_thread_handle_t th;
+    HANDLE th;
     results[i] = CURL_LAST; /* initialize with invalid value */
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
     th = CreateThread(NULL, 0, t3026_run_thread, &results[i], 0, NULL);
-#else
-    th = _beginthreadex(NULL, 0, t3026_run_thread, &results[i], 0, NULL);
-#endif
     if(!th) {
       curl_mfprintf(stderr, "%s:%d Couldn't create thread, errno %lu\n",
                     __FILE__, __LINE__, GetLastError());
@@ -84,8 +70,8 @@ static CURLcode test_lib3026(const char *URL)
 
 cleanup:
   for(i = 0; i < tid_count; i++) {
-    WaitForSingleObject((HANDLE)thread_handles[i], INFINITE);
-    CloseHandle((HANDLE)thread_handles[i]);
+    WaitForSingleObject(thread_handles[i], INFINITE);
+    CloseHandle(thread_handles[i]);
     if(results[i] != CURLE_OK) {
       curl_mfprintf(stderr, "%s:%d thread[%u]: curl_global_init() failed,"
                     "with code %d (%s)\n", __FILE__, __LINE__,
index 446d98a000839bcc137deeb629923060396c67e5..e3b50ff40ff24c5da72b238ca400c61409ca91d0 100644 (file)
@@ -68,7 +68,11 @@ static size_t write_memory_callback(char *contents, size_t size,
   return realsize;
 }
 
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
 static CURL_THREAD_RETURN_T CURL_STDCALL test_thread(void *ptr)
+#else
+static unsigned int test_thread(void *ptr)
+#endif
 {
   struct Ctx *ctx = (struct Ctx *)ptr;
   CURLcode res = CURLE_OK;
index c8b21beee90cb88d31c53f199d225cb4e247f164..2785b751340e5975349f958e078b37ab86cb5b24 100644 (file)
@@ -412,8 +412,7 @@ struct select_ws_wait_data {
   HANDLE signal; /* internal event to signal handle trigger */
   HANDLE abort;  /* internal event to abort waiting threads */
 };
-#include <process.h>
-static unsigned int WINAPI select_ws_wait_thread(void *lpParameter)
+static DWORD WINAPI select_ws_wait_thread(void *lpParameter)
 {
   struct select_ws_wait_data *data;
   HANDLE signal, handle, handles[2];
@@ -557,25 +556,25 @@ static unsigned int WINAPI select_ws_wait_thread(void *lpParameter)
 
 static HANDLE select_ws_wait(HANDLE handle, HANDLE signal, HANDLE abort)
 {
-  typedef uintptr_t curl_win_thread_handle_t;
   struct select_ws_wait_data *data;
-  curl_win_thread_handle_t thread;
 
   /* allocate internal waiting data structure */
   data = malloc(sizeof(struct select_ws_wait_data));
   if(data) {
+    HANDLE thread;
+
     data->handle = handle;
     data->signal = signal;
     data->abort = abort;
 
     /* launch waiting thread */
-    thread = _beginthreadex(NULL, 0, &select_ws_wait_thread, data, 0, NULL);
+    thread = CreateThread(NULL, 0, &select_ws_wait_thread, data, 0, NULL);
 
     /* free data if thread failed to launch */
     if(!thread) {
       free(data);
     }
-    return (HANDLE)thread;
+    return thread;
   }
   return NULL;
 }
index 26a5dd17f7087dc5567f06c8316d88aaaca89f20..02f91083e4f4beed5ca338480ebd9669325ecc93 100644 (file)
@@ -350,7 +350,7 @@ static SIGHANDLER_T old_sigbreak_handler = SIG_ERR;
 #endif
 
 #if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE)
-static unsigned int thread_main_id = 0;
+static DWORD thread_main_id = 0;
 static HANDLE thread_main_window = NULL;
 static HWND hidden_main_window = NULL;
 #endif
@@ -487,8 +487,7 @@ static LRESULT CALLBACK main_window_proc(HWND hwnd, UINT uMsg,
 }
 /* Window message queue loop for hidden main window, details see above.
  */
-#include <process.h>
-static unsigned int WINAPI main_window_loop(void *lpParameter)
+static DWORD WINAPI main_window_loop(void *lpParameter)
 {
   WNDCLASS wc;
   BOOL ret;
@@ -509,7 +508,7 @@ static unsigned int WINAPI main_window_loop(void *lpParameter)
                                       CW_USEDEFAULT, CW_USEDEFAULT,
                                       CW_USEDEFAULT, CW_USEDEFAULT,
                                       (HWND)NULL, (HMENU)NULL,
-                                      wc.hInstance, (LPVOID)NULL);
+                                      wc.hInstance, NULL);
   if(!hidden_main_window) {
     win32_perror("CreateWindowEx failed");
     return (DWORD)-1;
@@ -623,15 +622,10 @@ void install_signal_handlers(bool keep_sigalrm)
 #endif
 
 #if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE)
-  {
-    typedef uintptr_t curl_win_thread_handle_t;
-    curl_win_thread_handle_t thread;
-    thread = _beginthreadex(NULL, 0, &main_window_loop,
-                            (void *)GetModuleHandle(NULL), 0, &thread_main_id);
-    thread_main_window = (HANDLE)thread;
-    if(!thread_main_window || !thread_main_id)
-      logmsg("cannot start main window loop");
-  }
+  thread_main_window = CreateThread(NULL, 0, &main_window_loop,
+                                    GetModuleHandle(NULL), 0, &thread_main_id);
+  if(!thread_main_window || !thread_main_id)
+    logmsg("cannot start main window loop");
 #endif
 #endif
 }