Index: hostthre.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/hostthre.c,v
retrieving revision 1.24
diff -r1.24 hostthre.c
159a160,162
>   HANDLE event_thread_started; /* marks that the thread has initialized and started */
>   HANDLE mutex_terminate; /* serializes access to flag_terminate */
>   HANDLE event_terminate; /* flag for thread to terminate instead of calling callbacks */
164a168,263
> /* Data for synchronization between resolver thread and its parent */
> struct thread_sync_data {
>   HANDLE mutex_waiting;   /* thread_data.mutex_waiting duplicate */
>   HANDLE mutex_terminate; /* thread_data.mutex_terminate duplicate */
>   HANDLE event_terminate; /* thread_data.event_terminate duplicate */
>   char * hostname;        /* hostname to resolve, Curl_async.hostname duplicate */
> };
> 
> /* Destroy resolver thread synchronization data */
> void destroy_thread_sync_data(struct thread_sync_data * tsd) {
>   if (tsd->hostname) {
>     free(tsd->hostname);
>     tsd->hostname = NULL;
>   }
>   if (tsd->event_terminate) {
>     CloseHandle(tsd->event_terminate);
>     tsd->event_terminate = NULL;
>   }
>   if (tsd->mutex_terminate) {
>     CloseHandle(tsd->mutex_terminate);
>     tsd->mutex_terminate = NULL;
>   }
>   if (tsd->mutex_waiting) {
>     CloseHandle(tsd->mutex_waiting);
>     tsd->mutex_waiting = NULL;
>   }
> }
> 
> /* Initialize resolver thread synchronization data */
> BOOL init_thread_sync_data(struct thread_data * td, char * hostname, struct thread_sync_data * tsd) {
>   HANDLE curr_proc = GetCurrentProcess();
> 
>   memset(tsd, 0, sizeof(tsd));
>   if (!DuplicateHandle(curr_proc, td->mutex_waiting,
>                        curr_proc, &tsd->mutex_waiting, 0, FALSE,
>                        DUPLICATE_SAME_ACCESS)) {
>     /* failed to duplicate the mutex, no point in continuing */
>     destroy_thread_sync_data(tsd);
>     return FALSE;
>   }
>   if (!DuplicateHandle(curr_proc, td->mutex_terminate,
>                        curr_proc, &tsd->mutex_terminate, 0, FALSE,
>                        DUPLICATE_SAME_ACCESS)) {
>     /* failed to duplicate the mutex, no point in continuing */
>     destroy_thread_sync_data(tsd);
>     return FALSE;
>   }
>   if (!DuplicateHandle(curr_proc, td->event_terminate,
>                        curr_proc, &tsd->event_terminate, 0, FALSE,
>                        DUPLICATE_SAME_ACCESS)) {
>     /* failed to duplicate the event, no point in continuing */
>     destroy_thread_sync_data(tsd);
>     return FALSE;
>   }
>   /* Copying hostname string because original can be destroyed by parent
>    * thread during gethostbyname execution.
>    */
>   tsd->hostname = strdup(hostname);
>   if (!tsd->hostname) {
>     /* Memory allocation failed */
>     destroy_thread_sync_data(tsd);
>     return FALSE;
>   }
>   return TRUE;
> }
> 
> /* acquire resolver thread synchronization */
> BOOL acquire_thread_sync(struct thread_sync_data * tsd) {
>   /* is the thread initiator still waiting for us ? */
>   if (WaitForSingleObject(tsd->mutex_waiting, 0) == WAIT_TIMEOUT) {
>     /* yes, it is */
> 
>     /* Waiting access to event_terminate */
>     if (WaitForSingleObject(tsd->mutex_terminate, INFINITE) != WAIT_OBJECT_0) {
>       /* Something went wrong - now just ignoring */
>     }
>     else {
>       if (WaitForSingleObject(tsd->event_terminate, 0) != WAIT_TIMEOUT) {
>         /* Parent thread signaled us to terminate.
>          * This means that all data in conn->async is now destroyed
>          * and we cannot use it.
>          */
>       }
>       else {
>         return TRUE;
>       }
>     }
>   }
>   return FALSE;
> }
> 
> /* release resolver thread synchronization */
> void release_thread_sync(struct thread_sync_data * tsd) {
>   ReleaseMutex(tsd->mutex_terminate);
> }
> 
180c279
<   /* Duplicate the passed mutex handle.
---
>   /* Duplicate the passed mutex and event handles.
184,190c283,285
<   HANDLE mutex_waiting = NULL;
<   HANDLE curr_proc = GetCurrentProcess();
< 
<   if (!DuplicateHandle(curr_proc, td->mutex_waiting,
<                        curr_proc, &mutex_waiting, 0, FALSE,
<                        DUPLICATE_SAME_ACCESS)) {
<     /* failed to duplicate the mutex, no point in continuing */
---
>   struct thread_sync_data tsd = {0};
>   if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
>     /* thread synchronization data initialization failed */
203d297
<   he = gethostbyname (conn->async.hostname);
205,207c299,302
<   /* is the thread initiator still waiting for us ? */
<   if (WaitForSingleObject(mutex_waiting, 0) == WAIT_TIMEOUT) {
<     /* yes, it is */
---
>   /* Signaling that we have initialized all copies of data and handles we need */
>   SetEvent(td->event_thread_started);
> 
>   he = gethostbyname (tsd.hostname);
208a304,305
>   /* is parent thread waiting for us and are we able to access conn members ? */
>   if (acquire_thread_sync(&tsd)) {
213d309
< 
221a318
>     release_thread_sync(&tsd);
225c322
<   CloseHandle(mutex_waiting);
---
>   destroy_thread_sync_data(&tsd);
246a344
>   addrinfo hints = td->hints;
252,258c350,352
<   HANDLE mutex_waiting = NULL;
<   HANDLE curr_proc = GetCurrentProcess();
< 
<   if (!DuplicateHandle(curr_proc, td->mutex_waiting,
<                        curr_proc, &mutex_waiting, 0, FALSE,
<                        DUPLICATE_SAME_ACCESS)) {
<     /* failed to duplicate the mutex, no point in continuing */
---
>   struct thread_sync_data tsd = {0};
>   if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
>     /* thread synchronization data initialization failed */
270c364,365
<   rc = getaddrinfo(conn->async.hostname, service, &td->hints, &res);
---
>   /* Signaling that we have initialized all copies of data and handles we need */
>   SetEvent(td->event_thread_started);
272,274c367
<   /* is the thread initiator still waiting for us ? */
<   if (WaitForSingleObject(mutex_waiting, 0) == WAIT_TIMEOUT) {
<     /* yes, it is */
---
>   rc = getaddrinfo(tsd.hostname, service, &hints, &res);
275a369,370
>   /* is parent thread waiting for us and are we able to access conn members ? */
>   if (acquire_thread_sync(&tsd)) {
290a386
>     release_thread_sync(&tsd);
294c390
<   CloseHandle(mutex_waiting);
---
>   destroy_thread_sync_data(&tsd);
313a410,427
>     if (td->mutex_terminate && td->event_terminate) {
>       /* Signaling resolver thread to terminate */
>       if (WaitForSingleObject(td->mutex_terminate, INFINITE) == WAIT_OBJECT_0) {
>         SetEvent(td->event_terminate);
>         ReleaseMutex(td->mutex_terminate);
>       }
>       else {
>         /* Something went wrong - just ignoring it */
>       }
>     }
> 
>     if (td->mutex_terminate)
>       CloseHandle(td->mutex_terminate);
>     if (td->event_terminate)
>       CloseHandle(td->event_terminate);
>     if (td->event_thread_started)
>       CloseHandle(td->event_thread_started);
> 
343a458
>   HANDLE thread_and_event[2] = {0};
383a499,523
>   /* Create the mutex used to serialize access to event_terminated
>    * between us and resolver thread.
>    */
>   td->mutex_terminate = CreateMutex(NULL, FALSE, NULL);
>   if (td->mutex_terminate == NULL) {
>     Curl_destroy_thread_data(&conn->async);
>     SetLastError(EAGAIN);
>     return FALSE;
>   }
>   /* Create the event used to signal thread that it should terminate.
>    */
>   td->event_terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
>   if (td->event_terminate == NULL) {
>     Curl_destroy_thread_data(&conn->async);
>     SetLastError(EAGAIN);
>     return FALSE;
>   }
>   /* Create the event used by thread to inform it has initialized its own data.
>    */
>   td->event_thread_started = CreateEvent(NULL, TRUE, FALSE, NULL);
>   if (td->event_thread_started == NULL) {
>     Curl_destroy_thread_data(&conn->async);
>     SetLastError(EAGAIN);
>     return FALSE;
>   }
408a549,557
>   /* Waiting until the thread will initialize its data or it will exit due errors.
>    */
>   thread_and_event[0] = td->thread_hnd;
>   thread_and_event[1] = td->event_thread_started;
>   if (WaitForMultipleObjects(sizeof(thread_and_event) / sizeof(thread_and_event[0]), thread_and_event, FALSE, INFINITE) == WAIT_FAILED) {
>     /* The resolver thread has been created,
>      * most probably it works now - ignoring this "minor" error
>      */
>   }
