fix in-thread gethostbyname() for places

Uncovered by "place-parallel.rkt" test; not found in previous runs
because in-thread gethostbyname() wasn't enabled for Linux, but it
is now.
This commit is contained in:
Matthew Flatt 2011-09-16 16:18:10 -06:00
parent 33831cbd8a
commit b79c410e5b
4 changed files with 67 additions and 45 deletions

View File

@ -333,6 +333,7 @@ typedef struct Thread_Local_Variables {
struct Scheme_Hash_Table *fullpath_loaded_extensions_; struct Scheme_Hash_Table *fullpath_loaded_extensions_;
Scheme_Sleep_Proc scheme_place_sleep_; Scheme_Sleep_Proc scheme_place_sleep_;
struct Scheme_Bucket_Table *taint_intern_table_; struct Scheme_Bucket_Table *taint_intern_table_;
struct GHBN_Thread_Data *ghbn_thread_data_;
} Thread_Local_Variables; } Thread_Local_Variables;
#if defined(IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS) #if defined(IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS)
@ -667,6 +668,7 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
#define fullpath_loaded_extensions XOA (scheme_get_thread_local_variables()->fullpath_loaded_extensions_) #define fullpath_loaded_extensions XOA (scheme_get_thread_local_variables()->fullpath_loaded_extensions_)
#define scheme_place_sleep XOA (scheme_get_thread_local_variables()->scheme_place_sleep_) #define scheme_place_sleep XOA (scheme_get_thread_local_variables()->scheme_place_sleep_)
#define taint_intern_table XOA (scheme_get_thread_local_variables()->taint_intern_table_) #define taint_intern_table XOA (scheme_get_thread_local_variables()->taint_intern_table_)
#define ghbn_thread_data XOA (scheme_get_thread_local_variables()->ghbn_thread_data_)
/* **************************************** */ /* **************************************** */

View File

@ -555,6 +555,7 @@ void scheme_place_instance_destroy(int force)
GC_destruct_child_gc(); GC_destruct_child_gc();
#endif #endif
scheme_free_all_code(); scheme_free_all_code();
scheme_free_ghbn_data();
} }
static void make_kernel_env(void) static void make_kernel_env(void)

View File

@ -313,7 +313,7 @@ typedef struct SOCKADDR_IN mz_unspec_address;
/******************************* hostnames ************************************/ /******************************* hostnames ************************************/
#ifdef OS_X #if defined(OS_X) || defined(USE_PTHREAD_THREAD_TIMER)
# define PTHREADS_OK_FOR_GHBN # define PTHREADS_OK_FOR_GHBN
#endif #endif
@ -413,8 +413,6 @@ const char *mz_gai_strerror(int ecode)
# define MZ_LPTHREAD_START_ROUTINE void *(*)(void *) # define MZ_LPTHREAD_START_ROUTINE void *(*)(void *)
# endif # endif
static volatile int ghbn_lock;
typedef struct { typedef struct {
# ifdef USE_WINSOCK_TCP # ifdef USE_WINSOCK_TCP
HANDLE th; HANDLE th;
@ -426,43 +424,48 @@ typedef struct {
int done; int done;
} GHBN_Rec; } GHBN_Rec;
static struct mz_addrinfo * volatile ghbn_result;
static volatile int ghbn_err;
/* For in-thread DNS: */ /* For in-thread DNS: */
#define MZ_MAX_HOSTNAME_LEN 128 #define MZ_MAX_HOSTNAME_LEN 128
#define MZ_MAX_SERVNAME_LEN 32 #define MZ_MAX_SERVNAME_LEN 32
static char ghbn_hostname[MZ_MAX_HOSTNAME_LEN]; typedef struct GHBN_Thread_Data {
static char ghbn_servname[MZ_MAX_SERVNAME_LEN]; int ghbn_lock;
static struct mz_addrinfo ghbn_hints; char ghbn_hostname[MZ_MAX_HOSTNAME_LEN];
char ghbn_servname[MZ_MAX_SERVNAME_LEN];
struct mz_addrinfo ghbn_hints;
# ifdef USE_WINSOCK_TCP # ifdef USE_WINSOCK_TCP
HANDLE ready_sema; HANDLE ready_sema;
# else # else
int ready_fd; int ready_fd;
# endif # endif
struct mz_addrinfo *ghbn_result;
int ghbn_err;
} GHBN_Thread_Data;
static intptr_t getaddrinfo_in_thread(void *data) THREAD_LOCAL_DECL(GHBN_Thread_Data *ghbn_thread_data);
static intptr_t getaddrinfo_in_thread(void *_data)
XFORM_SKIP_PROC XFORM_SKIP_PROC
{ {
GHBN_Thread_Data *data = (GHBN_Thread_Data *)_data;
int ok; int ok;
struct mz_addrinfo *res, hints; struct mz_addrinfo *res, hints;
char hn_copy[MZ_MAX_HOSTNAME_LEN], sn_copy[MZ_MAX_SERVNAME_LEN]; char hn_copy[MZ_MAX_HOSTNAME_LEN], sn_copy[MZ_MAX_SERVNAME_LEN];
# ifndef USE_WINSOCK_TCP # ifndef USE_WINSOCK_TCP
int fd = ready_fd; int fd = data->ready_fd;
# endif # endif
if (ghbn_result) { if (data->ghbn_result) {
mz_freeaddrinfo(ghbn_result); mz_freeaddrinfo(data->ghbn_result);
ghbn_result = NULL; data->ghbn_result = NULL;
} }
strcpy(hn_copy, ghbn_hostname); strcpy(hn_copy, data->ghbn_hostname);
strcpy(sn_copy, ghbn_servname); strcpy(sn_copy, data->ghbn_servname);
memcpy(&hints, &ghbn_hints, sizeof(hints)); memcpy(&hints, &data->ghbn_hints, sizeof(hints));
# ifdef USE_WINSOCK_TCP # ifdef USE_WINSOCK_TCP
ReleaseSemaphore(ready_sema, 1, NULL); ReleaseSemaphore(data->ready_sema, 1, NULL);
# else # else
write(fd, "?", 1); write(fd, "?", 1);
# endif # endif
@ -471,8 +474,8 @@ static intptr_t getaddrinfo_in_thread(void *data)
sn_copy[0] ? sn_copy : NULL, sn_copy[0] ? sn_copy : NULL,
&hints, &res); &hints, &res);
ghbn_result = res; data->ghbn_result = res;
ghbn_err = ok; data->ghbn_err = ok;
# ifndef USE_WINSOCK_TCP # ifndef USE_WINSOCK_TCP
{ {
@ -487,7 +490,7 @@ static intptr_t getaddrinfo_in_thread(void *data)
static void release_ghbn_lock(GHBN_Rec *rec) static void release_ghbn_lock(GHBN_Rec *rec)
{ {
ghbn_lock = 0; ghbn_thread_data->ghbn_lock = 0;
# ifdef USE_WINSOCK_TCP # ifdef USE_WINSOCK_TCP
CloseHandle(rec->th); CloseHandle(rec->th);
# else # else
@ -497,7 +500,7 @@ static void release_ghbn_lock(GHBN_Rec *rec)
static int ghbn_lock_avail(Scheme_Object *_ignored) static int ghbn_lock_avail(Scheme_Object *_ignored)
{ {
return !ghbn_lock; return !ghbn_thread_data->ghbn_lock;
} }
static int ghbn_thread_done(Scheme_Object *_rec) static int ghbn_thread_done(Scheme_Object *_rec)
@ -509,9 +512,9 @@ static int ghbn_thread_done(Scheme_Object *_rec)
# ifdef USE_WINSOCK_TCP # ifdef USE_WINSOCK_TCP
if (WaitForSingleObject(rec->th, 0) == WAIT_OBJECT_0) { if (WaitForSingleObject(rec->th, 0) == WAIT_OBJECT_0) {
rec->result = ghbn_result; rec->result = ghbn_thread_data->ghbn_result;
ghbn_result = NULL; ghbn_thread_data->ghbn_result = NULL;
rec->err = ghbn_err; rec->err = ghbn_thread_data->ghbn_err;
rec->done = 1; rec->done = 1;
return 1; return 1;
} }
@ -519,9 +522,9 @@ static int ghbn_thread_done(Scheme_Object *_rec)
{ {
long v; long v;
if (read(rec->pin, &v, sizeof(long)) > 0) { if (read(rec->pin, &v, sizeof(long)) > 0) {
rec->result = ghbn_result; rec->result = ghbn_thread_data->ghbn_result;
ghbn_result = NULL; ghbn_thread_data->ghbn_result = NULL;
rec->err = ghbn_err; rec->err = ghbn_thread_data->ghbn_err;
rec->done = 1; rec->done = 1;
return 1; return 1;
} }
@ -560,34 +563,41 @@ static int MZ_GETADDRINFO(const char *name, const char *svc, struct mz_addrinfo
return mz_getaddrinfo(name, svc, hints, res); return mz_getaddrinfo(name, svc, hints, res);
} }
if (!ghbn_thread_data) {
ghbn_thread_data = (GHBN_Thread_Data *)malloc(sizeof(GHBN_Thread_Data));
memset(ghbn_thread_data, 0, sizeof(GHBN_Thread_Data));
}
rec = MALLOC_ONE_ATOMIC(GHBN_Rec); rec = MALLOC_ONE_ATOMIC(GHBN_Rec);
rec->done = 0; rec->done = 0;
scheme_block_until(ghbn_lock_avail, NULL, NULL, 0); scheme_block_until(ghbn_lock_avail, NULL, NULL, 0);
ghbn_lock = 1; ghbn_thread_data->ghbn_lock = 1;
if (name) if (name)
strcpy(ghbn_hostname, name); strcpy(ghbn_thread_data->ghbn_hostname, name);
else else
ghbn_hostname[0] = 0; ghbn_thread_data->ghbn_hostname[0] = 0;
if (svc) if (svc)
strcpy(ghbn_servname, svc); strcpy(ghbn_thread_data->ghbn_servname, svc);
else else
ghbn_servname[0] = 0; ghbn_thread_data->ghbn_servname[0] = 0;
memcpy(&ghbn_hints, hints, sizeof(ghbn_hints)); memcpy(&ghbn_thread_data->ghbn_hints, hints, sizeof(*hints));
# ifdef USE_WINSOCK_TCP # ifdef USE_WINSOCK_TCP
{ {
HANDLE ready_sema;
DWORD id; DWORD id;
intptr_t th; intptr_t th;
ready_sema = CreateSemaphore(NULL, 0, 1, NULL); ready_sema = CreateSemaphore(NULL, 0, 1, NULL);
ghbn_thread_data->ready_sema = ready_sema;
th = _beginthreadex(NULL, 5000, th = _beginthreadex(NULL, 5000,
(MZ_LPTHREAD_START_ROUTINE)getaddrinfo_in_thread, (MZ_LPTHREAD_START_ROUTINE)getaddrinfo_in_thread,
NULL, 0, &id); ghbn_thread_data, 0, &id);
WaitForSingleObject(ready_sema, INFINITE); WaitForSingleObject(ghbn_thread_data->ready_sema, INFINITE);
CloseHandle(ready_sema); CloseHandle(ghbn_thread_data->ready_sema);
rec->th = (HANDLE)th; rec->th = (HANDLE)th;
ok = 1; ok = 1;
@ -600,10 +610,10 @@ static int MZ_GETADDRINFO(const char *name, const char *svc, struct mz_addrinfo
} else { } else {
pthread_t t; pthread_t t;
rec->pin = p[0]; rec->pin = p[0];
ready_fd = p[1]; ghbn_thread_data->ready_fd = p[1];
if (pthread_create(&t, NULL, if (pthread_create(&t, NULL,
(MZ_LPTHREAD_START_ROUTINE)getaddrinfo_in_thread, (MZ_LPTHREAD_START_ROUTINE)getaddrinfo_in_thread,
NULL)) { ghbn_thread_data)) {
close(p[0]); close(p[0]);
close(p[1]); close(p[1]);
ok = 0; ok = 0;
@ -618,9 +628,9 @@ static int MZ_GETADDRINFO(const char *name, const char *svc, struct mz_addrinfo
if (!ok) { if (!ok) {
getaddrinfo_in_thread(rec); getaddrinfo_in_thread(rec);
rec->result = ghbn_result; rec->result = ghbn_thread_data->ghbn_result;
ghbn_result = NULL; ghbn_thread_data->ghbn_result = NULL;
rec->err = ghbn_err; rec->err = ghbn_thread_data->ghbn_err;
} }
} }
# endif # endif
@ -637,14 +647,22 @@ static int MZ_GETADDRINFO(const char *name, const char *svc, struct mz_addrinfo
# endif # endif
} }
ghbn_lock = 0; ghbn_thread_data->ghbn_lock = 0;
*res = rec->result; *res = rec->result;
return rec->err; return rec->err;
} }
void scheme_free_ghbn_data() {
if (ghbn_thread_data) {
free(ghbn_thread_data);
ghbn_thread_data = NULL;
}
}
#else #else
# define MZ_GETADDRINFO mz_getaddrinfo # define MZ_GETADDRINFO mz_getaddrinfo
void scheme_free_ghbn_data() { }
#endif #endif
#ifdef USE_SOCKETS_TCP #ifdef USE_SOCKETS_TCP

View File

@ -294,6 +294,7 @@ void register_network_evts();
void scheme_free_dynamic_extensions(void); void scheme_free_dynamic_extensions(void);
void scheme_free_all_code(void); void scheme_free_all_code(void);
void scheme_free_ghbn_data(void);
XFORM_NONGCING int scheme_is_multiprocessor(int now); XFORM_NONGCING int scheme_is_multiprocessor(int now);