From 9044fcbb5f4dbf2f873409f9a3fb725e6284b5d1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 6 Apr 2004 14:51:14 +0000 Subject: [PATCH] Gisle Vanem's fix for bug item #927979 reported by Nathan O'Sullivan. Good enough? --- lib/hostip.c | 73 +++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/lib/hostip.c b/lib/hostip.c index 6f25de94e0..8edd8d5aa6 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -60,6 +60,10 @@ #include #endif +#ifdef WIN32 +#include +#endif + #if (defined(NETWARE) && defined(__NOVELL_LIBC__)) #undef in_addr_t #define in_addr_t unsigned long @@ -70,6 +74,7 @@ #include "hostip.h" #include "hash.h" #include "share.h" +#include "strerror.h" #include "url.h" #define _MPRINTF_REPLACE /* use our functions only */ @@ -108,12 +113,8 @@ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn, char *hostname, int port, int *waitp); -#ifndef ENABLE_IPV6 -#if !defined(HAVE_GETHOSTBYNAME_R) || defined(USE_ARES) || \ - defined(USE_THREADING_GETHOSTBYNAME) + static struct hostent* pack_hostent(char** buf, struct hostent* orig); -#endif -#endif #ifdef USE_THREADING_GETHOSTBYNAME #ifdef DEBUG_THREADING_GETHOSTBYNAME @@ -126,12 +127,11 @@ static void trace_it (const char *fmt, ...); #define TRACE(x) #endif -static struct hostent* pack_hostent (char** buf, struct hostent* orig); static bool init_gethostbyname_thread (struct connectdata *conn, const char *hostname, int port); struct thread_data { HANDLE thread_hnd; - DWORD thread_id; + unsigned thread_id; DWORD thread_status; }; #endif @@ -1319,8 +1319,10 @@ static void trace_it (const char *fmt, ...) static int do_trace = -1; va_list args; - if (do_trace == -1) - do_trace = getenv("CURL_TRACE") ? 1 : 0; + if (do_trace == -1) { + const char *env = getenv("CURL_TRACE"); + do_trace = (env && atoi(env) > 0); + } if (!do_trace) return; va_start (args, fmt); @@ -1336,7 +1338,7 @@ static void trace_it (const char *fmt, ...) * * For builds without ARES/USE_IPV6, create a resolver thread and wait on it. */ -static DWORD WINAPI gethostbyname_thread (void *arg) +static unsigned __stdcall gethostbyname_thread (void *arg) { struct connectdata *conn = (struct connectdata*) arg; struct hostent *he; @@ -1355,19 +1357,21 @@ static DWORD WINAPI gethostbyname_thread (void *arg) TRACE(("Winsock-error %d, addr %s\n", conn->async.status, he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown")); return (rc); - /* An implicit ExitThread() here */ + /* An implicit _endthreadex() here */ } -/* complementary of ares_destroy +/* + * destroy_thread_data() cleans up async resolver data. + * Complementary of ares_destroy. */ -static void destroy_thread_data (struct connectdata *conn) +static void destroy_thread_data (struct Curl_async *async) { - if (conn->async.hostname) - free(conn->async.hostname); - if (conn->async.os_specific) - free(conn->async.os_specific); - conn->async.hostname = NULL; - conn->async.os_specific = NULL; + if (async->hostname) + free(async->hostname); + if (async->os_specific) + free(async->os_specific); + async->hostname = NULL; + async->os_specific = NULL; } /* @@ -1377,14 +1381,13 @@ static void destroy_thread_data (struct connectdata *conn) static bool init_gethostbyname_thread (struct connectdata *conn, const char *hostname, int port) { - struct thread_data *td = malloc(sizeof(*td)); + struct thread_data *td = calloc(sizeof(*td), 1); if (!td) { SetLastError(ENOMEM); return (0); } - memset (td, 0, sizeof(*td)); Curl_safefree(conn->async.hostname); conn->async.hostname = strdup(hostname); if (!conn->async.hostname) { @@ -1399,11 +1402,12 @@ static bool init_gethostbyname_thread (struct connectdata *conn, conn->async.dns = NULL; conn->async.os_specific = (void*) td; - td->thread_hnd = CreateThread(NULL, 0, gethostbyname_thread, + td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, gethostbyname_thread, conn, 0, &td->thread_id); if (!td->thread_hnd) { - TRACE(("CreateThread() failed; %lu\n", GetLastError())); - destroy_thread_data(conn); + SetLastError(errno); + TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn,errno))); + destroy_thread_data(&conn->async); return (0); } return (1); @@ -1438,19 +1442,23 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, status = WaitForSingleObject(td->thread_hnd, 1000UL*timeout); if (status == WAIT_OBJECT_0 || status == WAIT_ABANDONED) { - /* Thread finished before timeout; propagate Winsock error to this thread */ + /* Thread finished before timeout; propagate Winsock error to this thread. + * 'conn->async.done = TRUE' is set in host_callback(). + */ WSASetLastError(conn->async.status); GetExitCodeThread(td->thread_hnd, &td->thread_status); - TRACE(("status %lu, thread-status %08lX\n", status, td->thread_status)); + TRACE(("gethostbyname_thread() status %lu, thread retval %lu, ", + status, td->thread_status)); } else { conn->async.done = TRUE; - TerminateThread(td->thread_hnd, (DWORD)-1); td->thread_status = (DWORD)-1; + TRACE(("gethostbyname_thread() timeout, ")); } - TRACE(("gethostbyname_thread() retval %08lX, elapsed %lu ms\n", - td->thread_status, GetTickCount()-ticks)); + TRACE(("elapsed %lu ms\n", GetTickCount()-ticks)); + + CloseHandle(td->thread_hnd); if(entry) *entry = conn->async.dns; @@ -1464,13 +1472,14 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, rc = CURLE_OPERATION_TIMEDOUT; } else if(conn->async.done) { - failf(data, "Could not resolve host: %s (code %lu)", conn->name, conn->async.status); + failf(data, "Could not resolve host: %s; %s", + conn->name, Curl_strerror(conn,conn->async.status)); rc = CURLE_COULDNT_RESOLVE_HOST; } else rc = CURLE_OPERATION_TIMEDOUT; - destroy_thread_data(conn); + destroy_thread_data(&conn->async); /* close the connection, since we can't return failure here without cleaning up this connection properly */ Curl_disconnect(conn); @@ -1490,7 +1499,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn, if (conn->async.done) { /* we're done */ - destroy_thread_data(conn); + destroy_thread_data(&conn->async); if (!conn->async.dns) { TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n")); return CURLE_COULDNT_RESOLVE_HOST;