Coverage Report

Created: 2025-12-04 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/curl_threads.c
Line
Count
Source
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
25
#include "curl_setup.h"
26
27
#include <curl/curl.h>
28
29
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
30
#include <pthread.h>
31
#endif
32
33
#include "curl_threads.h"
34
35
#ifdef USE_THREADS_POSIX
36
37
struct Curl_actual_call {
38
  unsigned int (*func)(void *);
39
  void *arg;
40
};
41
42
static void *curl_thread_create_thunk(void *arg)
43
0
{
44
0
  struct Curl_actual_call *ac = arg;
45
0
  unsigned int (*func)(void *) = ac->func;
46
0
  void *real_arg = ac->arg;
47
48
0
  curlx_free(ac);
49
50
0
  (*func)(real_arg);
51
52
0
  return 0;
53
0
}
54
55
curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T
56
                                 (CURL_STDCALL *func) (void *), void *arg)
57
0
{
58
0
  curl_thread_t t = curlx_malloc(sizeof(pthread_t));
59
0
  struct Curl_actual_call *ac = curlx_malloc(sizeof(struct Curl_actual_call));
60
0
  int rc;
61
0
  if(!(ac && t))
62
0
    goto err;
63
64
0
  ac->func = func;
65
0
  ac->arg = arg;
66
67
0
  rc = pthread_create(t, NULL, curl_thread_create_thunk, ac);
68
0
  if(rc) {
69
0
    errno = rc;
70
0
    goto err;
71
0
  }
72
73
0
  return t;
74
75
0
err:
76
0
  curlx_free(t);
77
0
  curlx_free(ac);
78
0
  return curl_thread_t_null;
79
0
}
80
81
void Curl_thread_destroy(curl_thread_t *hnd)
82
0
{
83
0
  if(*hnd != curl_thread_t_null) {
84
0
    pthread_detach(**hnd);
85
0
    curlx_free(*hnd);
86
0
    *hnd = curl_thread_t_null;
87
0
  }
88
0
}
89
90
int Curl_thread_join(curl_thread_t *hnd)
91
0
{
92
0
  int ret = (pthread_join(**hnd, NULL) == 0);
93
94
0
  curlx_free(*hnd);
95
0
  *hnd = curl_thread_t_null;
96
97
0
  return ret;
98
0
}
99
100
#elif defined(USE_THREADS_WIN32)
101
102
curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T
103
                                 (CURL_STDCALL *func) (void *), void *arg)
104
{
105
  curl_thread_t t = CreateThread(NULL, 0, func, arg, 0, NULL);
106
  if(!t) {
107
    DWORD gle = GetLastError();
108
    /* !checksrc! disable ERRNOVAR 1 */
109
    errno = (gle == ERROR_ACCESS_DENIED ||
110
             gle == ERROR_NOT_ENOUGH_MEMORY) ?
111
             EACCES : EINVAL;
112
    return curl_thread_t_null;
113
  }
114
  return t;
115
}
116
117
void Curl_thread_destroy(curl_thread_t *hnd)
118
{
119
  if(*hnd != curl_thread_t_null) {
120
    CloseHandle(*hnd);
121
    *hnd = curl_thread_t_null;
122
  }
123
}
124
125
int Curl_thread_join(curl_thread_t *hnd)
126
{
127
  int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0);
128
129
  Curl_thread_destroy(hnd);
130
131
  return ret;
132
}
133
134
#endif /* USE_THREADS_* */