Coverage Report

Created: 2025-10-13 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PROJ/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
#include "curl_memory.h"
35
/* The last #include FILE should be: */
36
#include "memdebug.h"
37
38
#ifdef USE_THREADS_POSIX
39
40
struct Curl_actual_call {
41
  unsigned int (*func)(void *);
42
  void *arg;
43
};
44
45
static void *curl_thread_create_thunk(void *arg)
46
0
{
47
0
  struct Curl_actual_call *ac = arg;
48
0
  unsigned int (*func)(void *) = ac->func;
49
0
  void *real_arg = ac->arg;
50
51
0
  free(ac);
52
53
0
  (*func)(real_arg);
54
55
0
  return 0;
56
0
}
57
58
curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T
59
                                 (CURL_STDCALL *func) (void *), void *arg)
60
0
{
61
0
  curl_thread_t t = malloc(sizeof(pthread_t));
62
0
  struct Curl_actual_call *ac = malloc(sizeof(struct Curl_actual_call));
63
0
  int rc;
64
0
  if(!(ac && t))
65
0
    goto err;
66
67
0
  ac->func = func;
68
0
  ac->arg = arg;
69
70
0
  rc = pthread_create(t, NULL, curl_thread_create_thunk, ac);
71
0
  if(rc) {
72
0
    CURL_SETERRNO(rc);
73
0
    goto err;
74
0
  }
75
76
0
  return t;
77
78
0
err:
79
0
  free(t);
80
0
  free(ac);
81
0
  return curl_thread_t_null;
82
0
}
83
84
void Curl_thread_destroy(curl_thread_t *hnd)
85
0
{
86
0
  if(*hnd != curl_thread_t_null) {
87
0
    pthread_detach(**hnd);
88
0
    free(*hnd);
89
0
    *hnd = curl_thread_t_null;
90
0
  }
91
0
}
92
93
int Curl_thread_join(curl_thread_t *hnd)
94
0
{
95
0
  int ret = (pthread_join(**hnd, NULL) == 0);
96
97
0
  free(*hnd);
98
0
  *hnd = curl_thread_t_null;
99
100
0
  return ret;
101
0
}
102
103
#elif defined(USE_THREADS_WIN32)
104
105
curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T
106
                                 (CURL_STDCALL *func) (void *), void *arg)
107
{
108
  curl_thread_t t = CreateThread(NULL, 0, func, arg, 0, NULL);
109
  if(!t) {
110
    DWORD gle = GetLastError();
111
    /* !checksrc! disable ERRNOVAR 1 */
112
    int err = (gle == ERROR_ACCESS_DENIED ||
113
               gle == ERROR_NOT_ENOUGH_MEMORY) ?
114
               EACCES : EINVAL;
115
    CURL_SETERRNO(err);
116
    return curl_thread_t_null;
117
  }
118
  return t;
119
}
120
121
void Curl_thread_destroy(curl_thread_t *hnd)
122
{
123
  if(*hnd != curl_thread_t_null) {
124
    CloseHandle(*hnd);
125
    *hnd = curl_thread_t_null;
126
  }
127
}
128
129
int Curl_thread_join(curl_thread_t *hnd)
130
{
131
#ifdef UNDER_CE
132
  int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
133
#else
134
  int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0);
135
#endif
136
137
  Curl_thread_destroy(hnd);
138
139
  return ret;
140
}
141
142
#endif /* USE_THREADS_* */