157
161
FILE *stderr_file;
158
162
HANDLE mutex_waiting; /* marks that we are still waiting for a resolve */
159
163
HANDLE event_resolved; /* marks that the thread obtained the information */
164
HANDLE event_thread_started; /* marks that the thread has initialized and
166
HANDLE mutex_terminate; /* serializes access to flag_terminate */
167
HANDLE event_terminate; /* flag for thread to terminate instead of calling
160
169
#ifdef CURLRES_IPV6
161
170
struct addrinfo hints;
174
/* Data for synchronization between resolver thread and its parent */
175
struct thread_sync_data {
176
HANDLE mutex_waiting; /* thread_data.mutex_waiting duplicate */
177
HANDLE mutex_terminate; /* thread_data.mutex_terminate duplicate */
178
HANDLE event_terminate; /* thread_data.event_terminate duplicate */
179
char * hostname; /* hostname to resolve, Curl_async.hostname
183
/* Destroy resolver thread synchronization data */
185
void destroy_thread_sync_data(struct thread_sync_data * tsd)
189
tsd->hostname = NULL;
191
if (tsd->event_terminate) {
192
CloseHandle(tsd->event_terminate);
193
tsd->event_terminate = NULL;
195
if (tsd->mutex_terminate) {
196
CloseHandle(tsd->mutex_terminate);
197
tsd->mutex_terminate = NULL;
199
if (tsd->mutex_waiting) {
200
CloseHandle(tsd->mutex_waiting);
201
tsd->mutex_waiting = NULL;
205
/* Initialize resolver thread synchronization data */
207
BOOL init_thread_sync_data(struct thread_data * td,
209
struct thread_sync_data * tsd)
211
HANDLE curr_proc = GetCurrentProcess();
213
memset(tsd, 0, sizeof(tsd));
214
if (!DuplicateHandle(curr_proc, td->mutex_waiting,
215
curr_proc, &tsd->mutex_waiting, 0, FALSE,
216
DUPLICATE_SAME_ACCESS)) {
217
/* failed to duplicate the mutex, no point in continuing */
218
destroy_thread_sync_data(tsd);
221
if (!DuplicateHandle(curr_proc, td->mutex_terminate,
222
curr_proc, &tsd->mutex_terminate, 0, FALSE,
223
DUPLICATE_SAME_ACCESS)) {
224
/* failed to duplicate the mutex, no point in continuing */
225
destroy_thread_sync_data(tsd);
228
if (!DuplicateHandle(curr_proc, td->event_terminate,
229
curr_proc, &tsd->event_terminate, 0, FALSE,
230
DUPLICATE_SAME_ACCESS)) {
231
/* failed to duplicate the event, no point in continuing */
232
destroy_thread_sync_data(tsd);
235
/* Copying hostname string because original can be destroyed by parent
236
* thread during gethostbyname execution.
238
tsd->hostname = strdup(hostname);
239
if (!tsd->hostname) {
240
/* Memory allocation failed */
241
destroy_thread_sync_data(tsd);
247
/* acquire resolver thread synchronization */
249
BOOL acquire_thread_sync(struct thread_sync_data * tsd)
251
/* is the thread initiator still waiting for us ? */
252
if (WaitForSingleObject(tsd->mutex_waiting, 0) == WAIT_TIMEOUT) {
255
/* Waiting access to event_terminate */
256
if (WaitForSingleObject(tsd->mutex_terminate, INFINITE) != WAIT_OBJECT_0) {
257
/* Something went wrong - now just ignoring */
260
if (WaitForSingleObject(tsd->event_terminate, 0) != WAIT_TIMEOUT) {
261
/* Parent thread signaled us to terminate.
262
* This means that all data in conn->async is now destroyed
263
* and we cannot use it.
274
/* release resolver thread synchronization */
276
void release_thread_sync(struct thread_sync_data * tsd)
278
ReleaseMutex(tsd->mutex_terminate);
165
281
#if defined(CURLRES_IPV4)
167
283
* gethostbyname_thread() resolves a name, calls the Curl_addrinfo4_callback
177
293
struct hostent *he;
180
/* Duplicate the passed mutex handle.
296
/* Duplicate the passed mutex and event handles.
181
297
* This allows us to use it even after the container gets destroyed
182
298
* due to a resolver timeout.
184
HANDLE mutex_waiting = NULL;
185
HANDLE curr_proc = GetCurrentProcess();
187
if (!DuplicateHandle(curr_proc, td->mutex_waiting,
188
curr_proc, &mutex_waiting, 0, FALSE,
189
DUPLICATE_SAME_ACCESS)) {
190
/* failed to duplicate the mutex, no point in continuing */
300
struct thread_sync_data tsd = { 0,0,0,NULL };
301
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
302
/* thread synchronization data initialization failed */
202
314
WSASetLastError (conn->async.status = NO_DATA); /* pending status */
203
he = gethostbyname (conn->async.hostname);
205
/* is the thread initiator still waiting for us ? */
206
if (WaitForSingleObject(mutex_waiting, 0) == WAIT_TIMEOUT) {
209
/* Mark that we have obtained the information, and that we are
210
* calling back with it.
316
/* Signaling that we have initialized all copies of data and handles we
318
SetEvent(td->event_thread_started);
320
he = gethostbyname (tsd.hostname);
322
/* is parent thread waiting for us and are we able to access conn members? */
323
if (acquire_thread_sync(&tsd)) {
324
/* Mark that we have obtained the information, and that we are calling
212
326
SetEvent(td->event_resolved);
215
328
rc = Curl_addrinfo4_callback(conn, CURL_ASYNC_SUCCESS, he);
244
358
struct addrinfo *res;
245
359
char service [NI_MAXSERV];
361
struct addrinfo hints = td->hints;
248
363
/* Duplicate the passed mutex handle.
249
364
* This allows us to use it even after the container gets destroyed
250
365
* due to a resolver timeout.
252
HANDLE mutex_waiting = NULL;
253
HANDLE curr_proc = GetCurrentProcess();
255
if (!DuplicateHandle(curr_proc, td->mutex_waiting,
256
curr_proc, &mutex_waiting, 0, FALSE,
257
DUPLICATE_SAME_ACCESS)) {
258
/* failed to duplicate the mutex, no point in continuing */
367
struct thread_sync_data tsd = { 0,0,0,NULL };
368
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
369
/* thread synchronization data initialization failed */
268
379
WSASetLastError(conn->async.status = NO_DATA); /* pending status */
270
rc = getaddrinfo(conn->async.hostname, service, &td->hints, &res);
272
/* is the thread initiator still waiting for us ? */
273
if (WaitForSingleObject(mutex_waiting, 0) == WAIT_TIMEOUT) {
276
/* Mark that we have obtained the information, and that we are
277
* calling back with it.
381
/* Signaling that we have initialized all copies of data and handles we
383
SetEvent(td->event_thread_started);
385
rc = getaddrinfo(tsd.hostname, service, &hints, &res);
387
/* is parent thread waiting for us and are we able to access conn members? */
388
if (acquire_thread_sync(&tsd)) {
389
/* Mark that we have obtained the information, and that we are calling
279
391
SetEvent(td->event_resolved);
311
424
struct thread_data *td = (struct thread_data*) async->os_specific;
312
425
curl_socket_t sock = td->dummy_sock;
427
if (td->mutex_terminate && td->event_terminate) {
428
/* Signaling resolver thread to terminate */
429
if (WaitForSingleObject(td->mutex_terminate, INFINITE) == WAIT_OBJECT_0) {
430
SetEvent(td->event_terminate);
431
ReleaseMutex(td->mutex_terminate);
434
/* Something went wrong - just ignoring it */
438
if (td->mutex_terminate)
439
CloseHandle(td->mutex_terminate);
440
if (td->event_terminate)
441
CloseHandle(td->event_terminate);
442
if (td->event_thread_started)
443
CloseHandle(td->event_thread_started);
314
445
if (sock != CURL_SOCKET_BAD)
378
513
SetLastError(EAGAIN);
516
/* Create the mutex used to serialize access to event_terminated
517
* between us and resolver thread.
519
td->mutex_terminate = CreateMutex(NULL, FALSE, NULL);
520
if (td->mutex_terminate == NULL) {
521
Curl_destroy_thread_data(&conn->async);
522
SetLastError(EAGAIN);
525
/* Create the event used to signal thread that it should terminate.
527
td->event_terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
528
if (td->event_terminate == NULL) {
529
Curl_destroy_thread_data(&conn->async);
530
SetLastError(EAGAIN);
533
/* Create the event used by thread to inform it has initialized its own data.
535
td->event_thread_started = CreateEvent(NULL, TRUE, FALSE, NULL);
536
if (td->event_thread_started == NULL) {
537
Curl_destroy_thread_data(&conn->async);
538
SetLastError(EAGAIN);
382
542
td->stderr_file = stderr;
403
563
Curl_destroy_thread_data(&conn->async);
566
/* Waiting until the thread will initialize its data or it will exit due errors.
568
thread_and_event[0] = td->thread_hnd;
569
thread_and_event[1] = td->event_thread_started;
570
if (WaitForMultipleObjects(sizeof(thread_and_event) /
571
sizeof(thread_and_event[0]),
572
thread_and_event, FALSE,
573
INFINITE) == WAIT_FAILED) {
574
/* The resolver thread has been created,
575
* most probably it works now - ignoring this "minor" error
406
578
/* This socket is only to keep Curl_resolv_fdset() and select() happy;
407
579
* should never become signalled for read/write since it's unbound but
408
580
* Windows needs atleast 1 socket in select().
494
664
rc = CURLE_OUT_OF_MEMORY;
495
665
failf(data, "Could not resolve host: %s", curl_easy_strerror(rc));
667
else if(conn->async.done) {
668
if(conn->bits.httpproxy) {
669
failf(data, "Could not resolve proxy: %s; %s",
670
conn->proxy.dispname, Curl_strerror(conn, conn->async.status));
671
rc = CURLE_COULDNT_RESOLVE_PROXY;
674
failf(data, "Could not resolve host: %s; %s",
675
conn->host.name, Curl_strerror(conn, conn->async.status));
676
rc = CURLE_COULDNT_RESOLVE_HOST;
497
679
else if (td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) {
498
680
failf(data, "Resolving host timed out: %s", conn->host.name);
499
681
rc = CURLE_OPERATION_TIMEDOUT;
501
else if(conn->async.done) {
502
failf(data, "Could not resolve host: %s; %s",
503
conn->host.name, Curl_strerror(conn,conn->async.status));
504
rc = CURLE_COULDNT_RESOLVE_HOST;
507
684
rc = CURLE_OPERATION_TIMEDOUT;