From 6e1d5197114b24646391c60751f0c98a030dc411 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 11 Jun 2017 14:51:38 -0600 Subject: [PATCH] rktio: fix network problems --- racket/src/racket/src/network.c | 2 +- racket/src/rktio/Makefile.in | 11 +- racket/src/rktio/configure | 68 +++++++++ racket/src/rktio/configure.ac | 25 ++++ racket/src/rktio/{main.c => demo.c} | 49 ++++++- racket/src/rktio/rktio_config.h.in | 6 + racket/src/rktio/rktio_ltps.c | 4 +- racket/src/rktio/rktio_network.c | 213 ++++++++++++++++------------ racket/src/rktio/rktio_poll_set.c | 11 +- racket/src/rktio/rktio_private.h | 12 +- 10 files changed, 295 insertions(+), 106 deletions(-) rename racket/src/rktio/{main.c => demo.c} (92%) diff --git a/racket/src/racket/src/network.c b/racket/src/racket/src/network.c index 345ff49cde..24c7e1283e 100644 --- a/racket/src/racket/src/network.c +++ b/racket/src/racket/src/network.c @@ -796,7 +796,7 @@ struct mz_addrinfo *scheme_get_host_address(const char *address, int id, int *er ok = MZ_GETADDRINFO(address, service, &hints, &r); *err = ok; - + if (!ok) return r; else diff --git a/racket/src/rktio/Makefile.in b/racket/src/rktio/Makefile.in index af1790c183..91efd798f0 100644 --- a/racket/src/rktio/Makefile.in +++ b/racket/src/rktio/Makefile.in @@ -16,8 +16,11 @@ OBJS = rktio_filesystem.o \ all: $(OBJS) -demo: $(OBJS) main.o demo_fifo - $(CC) -o demo $(CFLAGS) $(LDFLAGS) main.o $(OBJS) +demo: rktio_demo + ./rktio_demo + +rktio_demo: $(OBJS) demo.o demo_fifo + $(CC) -o rktio_demo $(CFLAGS) $(LDFLAGS) demo.o $(OBJS) demo_fifo: mkfifo demo_fifo @@ -43,5 +46,5 @@ rktio_error.o: $(srcdir)/rktio_error.c $(RKTIO_HEADERS) rktio_main.o: $(srcdir)/rktio_main.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_main.o -c $(srcdir)/rktio_main.c -main.o: $(srcdir)/main.c $(RKTIO_HEADERS) - $(CC) $(CFLAGS) -I$(srcdir) -I. -o main.o -c $(srcdir)/main.c +demo.o: $(srcdir)/demo.c $(RKTIO_HEADERS) + $(CC) $(CFLAGS) -I$(srcdir) -I. -o demo.o -c $(srcdir)/demo.c diff --git a/racket/src/rktio/configure b/racket/src/rktio/configure index 06944221a0..65b35c1321 100755 --- a/racket/src/rktio/configure +++ b/racket/src/rktio/configure @@ -3104,6 +3104,52 @@ case "$host_os" in *mingw*) use_flag_pthread=no skip_iconv_check=yes + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lwinpthread" >&5 +$as_echo_n "checking for pthread_create in -lwinpthread... " >&6; } +if ${ac_cv_lib_winpthread_pthread_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwinpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_winpthread_pthread_create=yes +else + ac_cv_lib_winpthread_pthread_create=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_winpthread_pthread_create" >&5 +$as_echo "$ac_cv_lib_winpthread_pthread_create" >&6; } +if test "x$ac_cv_lib_winpthread_pthread_create" = xyes; then : + has_winpthread=yes +else + has_winpthread=no +fi + + if test "${has_winpthread}" = "yes" ; then + LIBS="${LIBS} -Wl,-Bstatic -lwinpthread" + fi ;; cygwin*) ;; @@ -3111,6 +3157,7 @@ case "$host_os" in ;; darwin*) PREFLAGS="$PREFLAGS -DOS_X -D_DARWIN_UNLIMITED_SELECT" + enable_pthread_by_default=yes try_kqueue_syscall=yes # Although select() generally works as well as poll() on OS X, @@ -3886,6 +3933,27 @@ if test "${LFS_CFLAGS}" != "" && test "${LFS_CFLAGS}" != "undefined"; then CFLAGS="${CFLAGS} ${LFS_CFLAGS}" fi +############### pthread ################### + +if test "${enable_pthread}" = "" ; then + if test "${enable_pthread_by_default}" = "yes" ; then + enable_pthread=yes + fi +fi + +if test "${enable_pthread}" = "yes" ; then + if test "${use_flag_pthread}" = "yes" ; then + PREFLAGS="$PREFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + fi + if test "${use_flag_posix_pthread}" = "yes" ; then + PREFLAGS="$PREFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT" + fi + +$as_echo "#define RKTIO_USE_PTHREADS 1" >>confdefs.h + +fi + ############## final output ################ diff --git a/racket/src/rktio/configure.ac b/racket/src/rktio/configure.ac index bbef567f87..2e250e0bc4 100644 --- a/racket/src/rktio/configure.ac +++ b/racket/src/rktio/configure.ac @@ -59,6 +59,11 @@ case "$host_os" in *mingw*) use_flag_pthread=no skip_iconv_check=yes + + AC_CHECK_LIB(winpthread, pthread_create, has_winpthread=yes, has_winpthread=no) + if test "${has_winpthread}" = "yes" ; then + LIBS="${LIBS} -Wl,-Bstatic -lwinpthread" + fi ;; cygwin*) ;; @@ -66,6 +71,7 @@ case "$host_os" in ;; darwin*) PREFLAGS="$PREFLAGS -DOS_X -D_DARWIN_UNLIMITED_SELECT" + enable_pthread_by_default=yes try_kqueue_syscall=yes # Although select() generally works as well as poll() on OS X, @@ -245,6 +251,25 @@ if test "${LFS_CFLAGS}" != "" && test "${LFS_CFLAGS}" != "undefined"; then CFLAGS="${CFLAGS} ${LFS_CFLAGS}" fi +############### pthread ################### + +if test "${enable_pthread}" = "" ; then + if test "${enable_pthread_by_default}" = "yes" ; then + enable_pthread=yes + fi +fi + +if test "${enable_pthread}" = "yes" ; then + if test "${use_flag_pthread}" = "yes" ; then + PREFLAGS="$PREFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + fi + if test "${use_flag_posix_pthread}" = "yes" ; then + PREFLAGS="$PREFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT" + fi + AC_DEFINE(RKTIO_USE_PTHREADS, 1, [Pthread enabled]) +fi + ############## final output ################ AC_SUBST(CC) diff --git a/racket/src/rktio/main.c b/racket/src/rktio/demo.c similarity index 92% rename from racket/src/rktio/main.c rename to racket/src/rktio/demo.c index 91550ebb7d..1074a765c8 100644 --- a/racket/src/rktio/main.c +++ b/racket/src/rktio/demo.c @@ -274,6 +274,49 @@ static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd check_valid(rktio_close(rktio, fd2)); } +void check_many_lookup(rktio_t *rktio) +{ +# define LOOKUPS_N 10 + int i, j; + rktio_addrinfo_lookup_t *lookup[LOOKUPS_N]; + rktio_addrinfo_t *addr; + rktio_poll_set_t *ps; + + for (i = 0; i < LOOKUPS_N; i++) { + if (i & 1) + lookup[i] = rktio_start_addrinfo_lookup(rktio, "localhost", 50+i, -1, 0, 1); + else + lookup[i] = rktio_start_addrinfo_lookup(rktio, "racket-lang.org", 50+i, -1, 0, 1); + check_valid(lookup[i]); + } + + for (j = 0; j < LOOKUPS_N; j++) { + ps = rktio_make_poll_set(rktio); + check_valid(ps); + + for (i = 0; i < LOOKUPS_N; i++) { + if (lookup[i]) + rktio_poll_add_addrinfo_lookup(rktio, lookup[i], ps); + } + + rktio_sleep(rktio, 0, ps, NULL); + rktio_poll_set_close(rktio, ps); + + for (i = 0; i < LOOKUPS_N; i++) { + if (lookup[i] && (rktio_poll_addrinfo_lookup_ready(rktio, lookup[i]) == RKTIO_POLL_READY)) { + if ((i % 3) == 2) + rktio_addrinfo_lookup_stop(rktio, lookup[i]); + else { + addr = rktio_addrinfo_lookup_get(rktio, lookup[i]); + check_valid(addr); + rktio_free_addrinfo(rktio, addr); + } + lookup[i] = NULL; + break; + } + } + } +} rktio_addrinfo_t *lookup_loop(rktio_t *rktio, const char *hostname, int portno, @@ -288,7 +331,7 @@ rktio_addrinfo_t *lookup_loop(rktio_t *rktio, lookup = rktio_start_addrinfo_lookup(rktio, hostname, portno, family, passive, tcp); check_valid(lookup); - + rktio_poll_add_addrinfo_lookup(rktio, lookup, ps); rktio_sleep(rktio, 0, ps, NULL); rktio_poll_set_close(rktio, ps); @@ -493,8 +536,10 @@ int main() { rktio_addrinfo_t *addr; rktio_listener_t *lnr; + + check_many_lookup(rktio); - addr = lookup_loop(rktio, "localhost", 4536, -1, 1, 1); + addr = lookup_loop(rktio, NULL, 4536, -1, 1, 1); lnr = rktio_listen(rktio, addr, 5, 1); check_valid(lnr); diff --git a/racket/src/rktio/rktio_config.h.in b/racket/src/rktio/rktio_config.h.in index 659d3f1fc2..107f25eb04 100644 --- a/racket/src/rktio/rktio_config.h.in +++ b/racket/src/rktio/rktio_config.h.in @@ -14,8 +14,14 @@ typedef long intptr_t; typedef unsigned long uintptr_t; #endif +/* Whether pthread is available */ +#undef RKTIO_USE_PTHREADS + /* When poll(), epoll(), kqueue(), etc. is available: */ #undef HAVE_POLL_SYSCALL #undef HAVE_EPOLL_SYSCALL #undef HAVE_INOTIFY_SYSCALL #undef HAVE_KQUEUE_SYSCALL + +/* Whether getaddrinfo() is available: */ +#undef HAVE_GETADDRINFO diff --git a/racket/src/rktio/rktio_ltps.c b/racket/src/rktio/rktio_ltps.c index d0da9e95d7..b9a2473975 100644 --- a/racket/src/rktio/rktio_ltps.c +++ b/racket/src/rktio/rktio_ltps.c @@ -92,7 +92,7 @@ rktio_ltps_t *rktio_open_ltps(rktio_t *rktio) #if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL) lt->fd = -1; #else - lt->fd_set = rktio_alloc_fdset_array(3); + lt->fd_set = rktio_make_poll_set(rktio); #endif lt->signaled = NULL; @@ -133,7 +133,7 @@ int rktio_ltps_close(rktio_t *rktio, rktio_ltps_t *lt) } free(lt); #else - rktio_free_fdset_array(lt->fd_set, 3); + rktio_poll_set_close(rktio, lt->fd_set); #endif return 1; diff --git a/racket/src/rktio/rktio_network.c b/racket/src/rktio/rktio_network.c index 8b95299e9e..9a045f2039 100644 --- a/racket/src/rktio/rktio_network.c +++ b/racket/src/rktio/rktio_network.c @@ -41,6 +41,21 @@ typedef struct sockaddr_in rktio_unspec_address; #define REGISTER_SOCKET(s) /**/ #define UNREGISTER_SOCKET(s) /**/ +# if defined(__linux__) || defined(OS_X) +/* RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT uses IPV6_V6ONLY for IPv6 + listeners when the same listener has an IPv4 address, which means + that the IpV6 listener accepts only IPv6 connections. This is used + with Linux, for example, because a port cannot have both an IPv4 + and IPv6 listener if the IPv6 one doesn't use IPV6_V6ONLY. (The + two listeners might be for different interfaces, in which case + IPV6_V6ONLY is not necessary, but we must err on the side of being + too restrictive. If IPV6_V6ONLY is not #defined or if setting the + option doesn't work, then the IPv6 addresses are silently ignored + when creating the listener (but only where there is at least once + IPv4 address). */ +# define RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT +# endif + #endif #ifdef CANT_SET_SOCKET_BUFSIZE @@ -147,10 +162,6 @@ struct rktio_udp_t { /* Host address lookup, including asynchronous-lookup support */ /*========================================================================*/ -#if defined(OS_X) || defined(USE_PTHREAD_THREAD_TIMER) -# define PTHREADS_OK_FOR_GHBN -#endif - # ifdef PROTOENT_IS_INT # define PROTO_P_PROTO PROTOENT_IS_INT # else @@ -168,7 +179,11 @@ static struct protoent *proto; #define RKTIO_SOCK_SVC_NAME_MAX_LEN 32 #if defined(HAVE_GETADDRINFO) || defined(__MINGW32__) -# define rktio_addrinfo_t addrinfo +struct rktio_addrinfo_t { + struct addrinfo ai; +}; +# define RKTIO_AS_ADDRINFO(x) (&(x)->ai) +# define RKTIO_AS_ADDRINFO_PTR(xp) ((struct addrinfo **)(xp)) #else struct rktio_addrinfo_t { int ai_flags; @@ -179,6 +194,8 @@ struct rktio_addrinfo_t { struct sockaddr *ai_addr; struct rktio_addrinfo_t *ai_next; }; +# define RKTIO_AS_ADDRINFO(x) x +# define RKTIO_AS_ADDRINFO_PTR(x) x #endif #if defined(__MINGW32__) && !defined(HAVE_GETADDRINFO) @@ -192,7 +209,7 @@ struct rktio_addrinfo_t { #ifdef HAVE_GETADDRINFO # define rktio_AI_PASSIVE AI_PASSIVE -# define do_getaddrinfo getaddrinfo +# define do_getaddrinfo(n, s, h, res) getaddrinfo(n, s, RKTIO_AS_ADDRINFO(h), RKTIO_AS_ADDRINFO_PTR(res)) # define do_freeaddrinfo freeaddrinfo # define do_gai_strerror gai_strerror #else @@ -284,11 +301,13 @@ static void free_lookup(rktio_addrinfo_lookup_t *lookup) { #if defined(RKTIO_SYSTEM_WINDOWS) || defined(RKTIO_USE_PTHREADS) if (lookup->result) - do_freeaddrinfo(lookup->result); + do_freeaddrinfo(RKTIO_AS_ADDRINFO(lookup->result)); #endif - - free(lookup->name); - free(lookup->svc); + + if (lookup->name) + free(lookup->name); + if (lookup->svc) + free(lookup->svc); free(lookup->hints); free(lookup); } @@ -315,7 +334,7 @@ static void init_lookup(rktio_addrinfo_lookup_t *lookup) #define GHBN_WAIT 1 #define GHBN_DONE 2 -#define GHBN_ADBANDONED 3 +#define GHBN_ABANDONED 3 # ifdef RKTIO_SYSTEM_WINDOWS @@ -350,27 +369,27 @@ static void ghbn_wait_exit(rktio_t *rktio) static void ghbn_lock(rktio_t *rktio) { - pthread_mutex_lock(rktio->ghbn_lock); + pthread_mutex_lock(&rktio->ghbn_lock); } static void ghbn_unlock(rktio_t *rktio) { - pthread_mutex_lock(rktio->ghbn_unlock); + pthread_mutex_unlock(&rktio->ghbn_lock); } static void ghbn_wait(rktio_t *rktio) { - pthread_cond_wait(rktio->ghbn_start, rktio->ghbn_lock); + pthread_cond_wait(&rktio->ghbn_start, &rktio->ghbn_lock); } static void ghbn_signal(rktio_t *rktio) { - pthread_cond_signal(rktio->ghbn_start); + pthread_cond_signal(&rktio->ghbn_start); } static void ghbn_wait_exit(rktio_t *rktio) { - pthread_join(rktio->th, NULL); + pthread_join(rktio->ghbn_th, NULL); } # endif @@ -386,17 +405,14 @@ static intptr_t getaddrinfo_in_thread(void *_data) while (rktio->ghbn_run) { lookup = rktio->ghbn_requests; if (lookup) { - rktio->ghbn->requests = lookup->next; + rktio->ghbn_requests = lookup->next; ghbn_unlock(rktio); /* Handle one lookup request: */ - err = do_getaddrinfo(lookup->name, - lookup->svc, - lookup->hints, - &result); - request->err = err; + err = do_getaddrinfo(lookup->name, lookup->svc, lookup->hints, &result); + lookup->err = err; if (!err) - request->result = result; + lookup->result = result; ghbn_lock(rktio); @@ -406,13 +422,13 @@ static intptr_t getaddrinfo_in_thread(void *_data) { long v = 1; do { - cr = write(lookup->done_fd[1], &v, sizeof(v)); - } while ((cr == -1) && (errno == EINTR)); + err = write(lookup->done_fd[1], &v, sizeof(v)); + } while ((err == -1) && (errno == EINTR)); reliably_close(lookup->done_fd[1]); } # endif - if (lookup->state == GHBN_ADBANDONED) { + if (lookup->mode == GHBN_ABANDONED) { # ifdef RKTIO_SYSTEM_WINDOWS CloseHandle(data->ready_sema); # else @@ -472,7 +488,7 @@ static int ghbn_init(rktio_t *rktio) get_posix_error(); return 0; } - if (pthread_create(&rktio->th, NULL, + if (pthread_create(&rktio->ghbn_th, NULL, (RKTIO_LPTHREAD_START_ROUTINE)getaddrinfo_in_thread, rktio)) { return 0; @@ -495,6 +511,8 @@ void rktio_free_ghbn(rktio_t *rktio) static rktio_addrinfo_lookup_t *start_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup) { + lookup->mode = GHBN_WAIT; + if (!rktio->ghbn_started) { rktio->ghbn_run = 1; if (!ghbn_init(rktio)) @@ -503,40 +521,41 @@ static rktio_addrinfo_lookup_t *start_lookup(rktio_t *rktio, rktio_addrinfo_look } # ifdef RKTIO_SYSTEM_WINDOWS - { - HANDLE ready_sema; - unsigned int id; - intptr_t th; + { + HANDLE ready_sema; + unsigned int id; + intptr_t th; - lookup->done_sema = CreateSemaphore(NULL, 0, 1, NULL); - if (!lookup->done_sema) { - get_windows_error(); - free_lookup(lookup); - return NULL; - } - } -# else - if (pipe(lookup->done_fd)) { - get_posix_error(); + lookup->done_sema = CreateSemaphore(NULL, 0, 1, NULL); + if (!lookup->done_sema) { + get_windows_error(); free_lookup(lookup); return NULL; - } else { - fcntl(lookup->done_fd[0], F_SETFL, RKTIO_NONBLOCKING); } + } +# else + if (pipe(lookup->done_fd)) { + get_posix_error(); + free_lookup(lookup); + return NULL; + } else { + fcntl(lookup->done_fd[0], F_SETFL, RKTIO_NONBLOCKING); + } # endif - ghbn_lock(rktio); - lookup->next = rktio->ghbn_requests; - ghbn_requests = lookup; - ghbn_signal(rktio); - ghbn_unlock(rktio); + ghbn_lock(rktio); + lookup->next = rktio->ghbn_requests; + rktio->ghbn_requests = lookup; + ghbn_signal(rktio); + ghbn_unlock(rktio); - return lookup; - } + return lookup; } int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup) { + int done = 0; + ghbn_lock(rktio); if (lookup->mode == GHBN_DONE) { @@ -545,10 +564,10 @@ int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lo } # ifdef RKTIO_SYSTEM_WINDOWS - if (WaitForSingleObject(lookup->done_sema, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(lookup->done_sema, 0) == WAIT_OBJECT_0) { CloseHandle(lookup->done_sema); - else - return 0; + done = 1; + } # else { long v; @@ -558,19 +577,20 @@ int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lo } while ((cr == -1) && (errno == EINTR)); if (cr > 0) { reliably_close(lookup->done_fd[0]); - } else - return 0; + done = 1; + } } # endif - lookup->mode = GHBN_DONE; + if (done) + lookup->mode = GHBN_DONE; ghbn_unlock(rktio); - return RKTIO_POLL_READY; + return (done ? RKTIO_POLL_READY : 0); } -void rktio_poll_add_addr_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_t *fds) +void rktio_poll_add_addrinfo_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_t *fds) { ghbn_lock(rktio); @@ -586,12 +606,12 @@ void rktio_poll_add_addr_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_add_handle(lookup->done_sema, fds, 1); # else { - void *fds2; + rktio_poll_set_t *fds2; fds2 = RKTIO_GET_FDSET(fds, 2); - RKTIO_FD_SET(lookup->done_fd[0], (fd_set *)fds); - RKTIO_FD_SET(lookup->done_fd[0], (fd_set *)fds2); + RKTIO_FD_SET(lookup->done_fd[0], fds); + RKTIO_FD_SET(lookup->done_fd[0], fds2); } # endif } @@ -600,7 +620,7 @@ void rktio_addrinfo_lookup_stop(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup) { ghbn_lock(rktio); if (lookup->mode != GHBN_DONE) { - lookup->mode == GHBN_ABANDONED; + lookup->mode = GHBN_ABANDONED; ghbn_unlock(rktio); } else { ghbn_unlock(rktio); @@ -666,7 +686,10 @@ rktio_addrinfo_t *rktio_addrinfo_lookup_get(rktio_t *rktio, rktio_addrinfo_looku free_lookup(lookup); - return result; + if (err) + return NULL; + else + return result; } #endif @@ -698,25 +721,25 @@ rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio, hints = malloc(sizeof(rktio_addrinfo_t)); memset(hints, 0, sizeof(struct rktio_addrinfo_t)); - hints->ai_family = ((family < 0) ? PF_UNSPEC : family); + RKTIO_AS_ADDRINFO(hints)->ai_family = ((family < 0) ? PF_UNSPEC : family); if (passive) { - hints->ai_flags |= rktio_AI_PASSIVE; + RKTIO_AS_ADDRINFO(hints)->ai_flags |= rktio_AI_PASSIVE; } if (tcp) { - hints->ai_socktype = SOCK_STREAM; + RKTIO_AS_ADDRINFO(hints)->ai_socktype = SOCK_STREAM; # ifndef PROTOENT_IS_INT if (!proto) { proto = getprotobyname("tcp"); } # endif - hints->ai_protocol= PROTO_P_PROTO; + RKTIO_AS_ADDRINFO(hints)->ai_protocol= PROTO_P_PROTO; } else { - hints->ai_socktype = SOCK_DGRAM; + RKTIO_AS_ADDRINFO(hints)->ai_socktype = SOCK_DGRAM; } lookup = malloc(sizeof(rktio_addrinfo_lookup_t)); - lookup->name = strdup(hostname); - lookup->svc = strdup(service); + lookup->name = (hostname ? strdup(hostname) : NULL); + lookup->svc = (service ? strdup(service) : NULL); lookup->hints = hints; init_lookup(lookup); @@ -725,7 +748,7 @@ rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio, void rktio_free_addrinfo(rktio_t *rktio, rktio_addrinfo_t *a) { - do_freeaddrinfo(a); + do_freeaddrinfo(RKTIO_AS_ADDRINFO(a)); } const char *rktio_gai_strerror(int errnum) @@ -1042,11 +1065,13 @@ static rktio_connect_t *try_connect(rktio_t *rktio, rktio_connect_t *conn) rktio_socket_t s; addr = conn->addr; - s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + s = socket(RKTIO_AS_ADDRINFO(addr)->ai_family, + RKTIO_AS_ADDRINFO(addr)->ai_socktype, + RKTIO_AS_ADDRINFO(addr)->ai_protocol); if (s != INVALID_SOCKET) { int status, inprogress; if (!conn->src - || !bind(s, conn->src->ai_addr, conn->src->ai_addrlen)) { + || !bind(s, RKTIO_AS_ADDRINFO(conn->src)->ai_addr, RKTIO_AS_ADDRINFO(conn->src)->ai_addrlen)) { #ifdef RKTIO_SYSTEM_WINDOWS unsigned long ioarg = 1; ioctlsocket(s, FIONBIO, &ioarg); @@ -1055,7 +1080,7 @@ static rktio_connect_t *try_connect(rktio_t *rktio, rktio_connect_t *conn) fcntl(s, F_SETFL, RKTIO_NONBLOCKING); RKTIO_WHEN_SET_SOCKBUF_SIZE(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(int))); #endif - status = connect(s, addr->ai_addr, addr->ai_addrlen); + status = connect(s, RKTIO_AS_ADDRINFO(addr)->ai_addr, RKTIO_AS_ADDRINFO(addr)->ai_addrlen); #ifdef RKTIO_SYSTEM_UNIX if (status) status = errno; @@ -1128,9 +1153,9 @@ rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *conn) if (errid) { rktio_close(rktio, rfd); - if (conn->addr->ai_next) { + if (RKTIO_AS_ADDRINFO(conn->addr)->ai_next) { /* try the next one */ - conn->addr = conn->addr->ai_next; + conn->addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(conn->addr)->ai_next; if (try_connect(rktio, conn)) { set_racket_error(RKTIO_ERROR_CONNECT_TRYING_NEXT); return NULL; @@ -1189,16 +1214,16 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo int any_v4 = 0, any_v6 = 0; #endif - for (addr = src; addr; addr = addr->ai_next) { + for (addr = src; addr; addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next) { #ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT - if (addr->ai_family == RKTIO_PF_INET) + if (RKTIO_AS_ADDRINFO(addr)->ai_family == RKTIO_PF_INET) any_v4 = 1; - else if (addr->ai_family == PF_INET6) + else if (RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6) any_v6 = 1; #endif count++; } - + { rktio_socket_t s; #ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT @@ -1212,34 +1237,36 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo for (addr = src; addr; ) { #ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT - if ((v6_loop && (addr->ai_family != PF_INET6)) - || (skip_v6 && (addr->ai_family == PF_INET6))) { - addr = addr->ai_next; + if ((v6_loop && (RKTIO_AS_ADDRINFO(addr)->ai_family != PF_INET6)) + || (skip_v6 && (RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6))) { + addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next; if (v6_loop && !addr) { v6_loop = 0; skip_v6 = 1; - addr = tcp_listen_addr; + addr = src; } continue; } #endif - s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + s = socket(RKTIO_AS_ADDRINFO(addr)->ai_family, + RKTIO_AS_ADDRINFO(addr)->ai_socktype, + RKTIO_AS_ADDRINFO(addr)->ai_protocol); if (s != INVALID_SOCKET) get_socket_error(); #ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT if (s == INVALID_SOCKET) { /* Maybe it failed because IPv6 is not available: */ - if ((addr->ai_family == PF_INET6) && (errno == EAFNOSUPPORT)) { + if ((RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6) && (errno == EAFNOSUPPORT)) { if (any_v4 && !pos) { /* Let client known that maybe we can make it work with just IPv4. */ - set_racket_option(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4); + set_racket_error(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4); } } } if (s != INVALID_SOCKET) { - if (any_v4 && (addr->ai_family == PF_INET6)) { + if (any_v4 && (RKTIO_AS_ADDRINFO(addr)->ai_family == PF_INET6)) { int ok; # ifdef IPV6_V6ONLY int on = 1; @@ -1250,7 +1277,7 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo if (ok) { if (!pos) { /* IPV6_V6ONLY doesn't work */ - set_racket_option(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4); + set_racket_error(RKTIO_ERROR_TRY_AGAIN_WITH_IPV4); s = INVALID_SOCKET; } else { get_socket_error(); @@ -1275,11 +1302,11 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo } if (first_was_zero) { - ((struct sockaddr_in *)addr->ai_addr)->sin_port = no_port; + ((struct sockaddr_in *)RKTIO_AS_ADDRINFO(addr)->ai_addr)->sin_port = no_port; } - if (!bind(s, addr->ai_addr, addr->ai_addrlen)) { + if (!bind(s, RKTIO_AS_ADDRINFO(addr)->ai_addr, RKTIO_AS_ADDRINFO(addr)->ai_addrlen)) { if (first_time) { - if (((struct sockaddr_in *)addr->ai_addr)->sin_port == 0) { + if (((struct sockaddr_in *)RKTIO_AS_ADDRINFO(addr)->ai_addr)->sin_port == 0) { no_port = get_no_portno(rktio, s); first_was_zero = 1; if (no_port < 0) { @@ -1327,7 +1354,7 @@ rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *src, int backlo break; } - addr = addr->ai_next; + addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next; #ifdef RKTIO_TCP_LISTEN_IPV6_ONLY_SOCKOPT if (!addr && v6_loop) { diff --git a/racket/src/rktio/rktio_poll_set.c b/racket/src/rktio/rktio_poll_set.c index 36865082b0..3c897c8490 100644 --- a/racket/src/rktio/rktio_poll_set.c +++ b/racket/src/rktio/rktio_poll_set.c @@ -733,7 +733,10 @@ void rktio_collapse_win_fd(rktio_poll_set_t *fds) static rktio_poll_set_t *alloc_fdset_arrays() { + void *p; p = malloc((3 * sizeof(fd_set)) + sizeof(int)); + *(int *)((char *)p + (3 * sizeof(fd_set))) = 0; + return p; } static void free_fdset_arrays(rktio_poll_set_t *fds) @@ -869,7 +872,13 @@ void rktio_free_global_poll_set(rktio_t *rktio) { rktio_poll_set_t *rktio_make_poll_set(rktio_t *rktio) { - return alloc_fdset_arrays(); + rktio_poll_set_t *fds = alloc_fdset_arrays(); + + RKTIO_FD_ZERO(fds); + RKTIO_FD_ZERO(RKTIO_GET_FDSET(fds, 1)); + RKTIO_FD_ZERO(RKTIO_GET_FDSET(fds, 2)); + + return fds; } void rktio_poll_set_close(rktio_t *rktio, rktio_poll_set_t *fds) diff --git a/racket/src/rktio/rktio_private.h b/racket/src/rktio/rktio_private.h index 3bc3c59cd7..07c83d0d5d 100644 --- a/racket/src/rktio/rktio_private.h +++ b/racket/src/rktio/rktio_private.h @@ -5,10 +5,16 @@ # define RKTIO_SYSTEM_UNIX #endif +#if defined(__APPLE__) && defined(__MACH__) && !defined(OS_X) +# define OS_X +#endif #ifdef RKTIO_SYSTEM_WINDOWS # include #endif +#ifdef RKTIO_USE_PTHREADS +# include +#endif #if RKTIO_SYSTEM_WINDOWS # define USE_FAR_RKTIO_FDCALLS @@ -47,14 +53,14 @@ struct rktio_t { #if defined(RKTIO_SYSTEM_WINDOWS) || defined(RKTIO_USE_PTHREADS) int ghbn_started, ghbn_run; - struct rktio_addr_lookup_t *ghbn_requests; + struct rktio_addrinfo_lookup_t *ghbn_requests; # ifdef RKTIO_USE_PTHREADS - HANDLE ghbn_th; + pthread_t ghbn_th; pthread_mutex_t ghbn_lock; pthread_cond_t ghbn_start; # endif # ifdef RKTIO_SYSTEM_WINDOWS - pthread_t ghbn_th; + HANDLE ghbn_th; HANDLE ghbn_lock; HANDLE ghbn_start; # endif