]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
bugfix #678: Use poll to support > 1024 fds
authorWillem Toorop <willem@nlnetlabs.nl>
Tue, 18 Oct 2016 22:47:04 +0000 (17:47 -0500)
committerWillem Toorop <willem@nlnetlabs.nl>
Tue, 18 Oct 2016 22:47:04 +0000 (17:47 -0500)
Thanks William King

Changelog
configure.ac
m4/ax_config_feature.m4 [new file with mode: 0644]
m4/ax_have_poll.m4 [new file with mode: 0644]
net.c
resolver.c

index 2ca00c64e9f7efd0ed105f2f3d8dfe6fd0950372..b8c180c926a174179e7c1f96b7ca5e94ad7818c2 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -92,6 +92,8 @@ TBD
          Thanks Harald Jenny
        * bugfix #680: ldns fails to reject invalidly formatted
          RFC 7553 URI RRs.  Thanks Robert Edmonds
+       * bugfix #678: Use poll i.s.o. select to support > 1024 fds
+         Thanks William King
 
 1.6.17 2014-01-10
        * Fix ldns_dnssec_zone_new_frm_fp_l to allow the last parsed line of a
index b542b24457b317748e5358a996070c6c52c72fa7..ed6aa572493b006671c0546c46f3502f91f73568 100644 (file)
@@ -181,6 +181,13 @@ case "$enable_stderr_msgs" in
         ;;
 esac
 
+AX_HAVE_POLL(
+  [AX_CONFIG_FEATURE_ENABLE(poll)],
+  [AX_CONFIG_FEATURE_DISABLE(poll)])
+AX_CONFIG_FEATURE(
+  [poll], [This platform supports poll(7)],
+  [HAVE_POLL], [This platform supports poll(7).])
+
 # check for python
 PYTHON_X_CFLAGS=""
 ldns_with_pyldns=no
@@ -832,6 +839,15 @@ void *memmove(void *dest, const void *src, size_t n);
 #ifndef HAVE_STRLCPY
 size_t strlcpy(char *dst, const char *src, size_t siz);
 #endif
+
+#ifdef USE_WINSOCK
+#define SOCK_INVALID INVALID_SOCKET
+#define close_socket(_s) if (_s > SOCK_INVALID) {closesocket(_s); _s = SOCK_INVALID;}
+#else
+#define SOCK_INVALID -1
+#define close_socket(_s) if (_s > SOCK_INVALID) {close(_s); _s = SOCK_INVALID;}
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/m4/ax_config_feature.m4 b/m4/ax_config_feature.m4
new file mode 100644 (file)
index 0000000..e205723
--- /dev/null
@@ -0,0 +1,156 @@
+# ===========================================================================
+#     http://www.gnu.org/software/autoconf-archive/ax_config_feature.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CONFIG_FEATURE(FEATURE-NAME, FEATURE-DESCRIPTION, DEFINE, DEFINE-DESCRIPTION, [ACTION-IF-ENABLED [, ACTION-IF-NOT-ENABLED]])
+#
+# DESCRIPTION
+#
+#   AX_CONFIG_FEATURE is a simple wrapper for AC_ARG_ENABLE, it enables the
+#   feature FEATURE-NAME and AC_DEFINEs the passed DEFINE, depending on the
+#   user choice. DESCRIPTION will be used for AC_DEFINEs. ACTION-IF-ENABLED
+#   and ACTION-IF-NOT-ENABLED are the actions that will be run. A feature is
+#   enabled by default, in order to change this behaviour use the
+#   AX_CONFIG_FEATURE_DEFAULT_ENABLED and AX_CONFIG_FEATURE_DEFAULT_DISABLED
+#   macros.
+#
+#   A simple example:
+#
+#     AX_CONFIG_FEATURE_DEFAULT_ENABLED
+#     AX_CONFIG_FEATURE(feature_xxxxx, [turns on/off XXXXX support],
+#                       HAVE_XXXXX, [Define if you want XXXXX support])
+#
+#     ...
+#
+#     AX_CONFIG_FEATURE_DEFAULT_DISABLED
+#     AX_CONFIG_FEATURE(feature_yyyyy, [turns on/off YYYYY support],
+#                       HAVE_YYYYY, [Define if you want YYYYY support],
+#                       [enable_yyyyy="yes"], [enable_yyyyy="no"])
+#     AM_CONDITIONAL(YYYYY, [test "$enable_yyyyy" = "yes"])
+#
+#     AX_CONFIG_FEATURE_DEFAULT_ENABLED
+#     AX_CONFIG_FEATURE(...)
+#
+#     ...
+#
+#   If you have lot of features and you want a verbose dumping of each user
+#   selection use AX_CONFIG_FEATURE_VERBOSE. Use AX_CONFIG_FEATURE_SILENT in
+#   order to remove a previously AX_CONFIG_FEATURE_VERBOSE. By default
+#   features are silent.
+#
+#   Use AX_CONFIG_FEATURE_ENABLE or AX_CONFIG_FEATURE_DISABLE in order to
+#   enable or disable a specific feature.
+#
+#   Another simple example:
+#
+#     AS_IF([some_test_here],[AX_CONFIG_FEATURE_ENABLE(feature_xxxxx)],[])
+#
+#     AX_CONFIG_FEATURE(feature_xxxxx, [turns on/off XXXXX support],
+#                       HAVE_XXXXX, [Define if you want XXXXX support])
+#     AX_CONFIG_FEATURE(feature_yyyyy, [turns on/off YYYYY support],
+#                       HAVE_YYYYY, [Define if you want YYYYY support],
+#                       [enable_yyyyy="yes"], [enable_yyyyy="no"])
+#
+#     ...
+#
+#   NOTE: AX_CONFIG_FEATURE_ENABLE() must be placed first of the relative
+#   AX_CONFIG_FEATURE() macro ...
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Francesco Salvestrini <salvestrini@users.sourceforge.net>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 10
+
+AC_DEFUN([AX_CONFIG_FEATURE],[ dnl
+m4_pushdef([FEATURE], patsubst([$1], -, _))dnl
+
+AC_ARG_ENABLE([$1],AS_HELP_STRING([--enable-$1],[$2]),[
+case "${enableval}" in
+   yes)
+     ax_config_feature_[]FEATURE[]="yes"
+     ;;
+   no)
+     ax_config_feature_[]FEATURE[]="no"
+     ;;
+   *)
+     AC_MSG_ERROR([bad value ${enableval} for feature --$1])
+     ;;
+esac
+])
+
+AS_IF([test "$ax_config_feature_[]FEATURE[]" = yes],[ dnl
+  AC_DEFINE([$3])
+  $5
+  AS_IF([test "$ax_config_feature_verbose" = yes],[ dnl
+    AC_MSG_NOTICE([Feature $1 is enabled])
+  ])
+],[ dnl
+  $6
+  AS_IF([test "$ax_config_feature_verbose" = yes],[ dnl
+    AC_MSG_NOTICE([Feature $1 is disabled])
+  ])
+])
+
+AH_TEMPLATE([$3],[$4])
+
+m4_popdef([FEATURE])dnl
+])
+
+dnl Feature global
+AC_DEFUN([AX_CONFIG_FEATURE_VERBOSE],[ dnl
+  ax_config_feature_verbose=yes
+])
+
+dnl Feature global
+AC_DEFUN([AX_CONFIG_FEATURE_SILENT],[ dnl
+  ax_config_feature_verbose=no
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_DEFAULT_ENABLED], [
+  ax_config_feature_[]FEATURE[]_default=yes
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_DEFAULT_DISABLED], [
+  ax_config_feature_[]FEATURE[]_default=no
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_ENABLE],[ dnl
+  ax_config_feature_[]patsubst([$1], -, _)[]=yes
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_DISABLE],[ dnl
+  ax_config_feature_[]patsubst([$1], -, _)[]=no
+])
diff --git a/m4/ax_have_poll.m4 b/m4/ax_have_poll.m4
new file mode 100644 (file)
index 0000000..14d3d4b
--- /dev/null
@@ -0,0 +1,72 @@
+# ===========================================================================
+#       http://www.gnu.org/software/autoconf-archive/ax_have_poll.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_HAVE_POLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#   AX_HAVE_PPOLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+#   This macro determines whether the system supports the poll I/O event
+#   interface. A neat usage example would be:
+#
+#     AX_HAVE_POLL(
+#       [AX_CONFIG_FEATURE_ENABLE(poll)],
+#       [AX_CONFIG_FEATURE_DISABLE(poll)])
+#     AX_CONFIG_FEATURE(
+#       [poll], [This platform supports poll(7)],
+#       [HAVE_POLL], [This platform supports poll(7).])
+#
+#   Some systems -- most notably Linux kernel 2.6.16 and later -- also have
+#   the variant ppoll(). The availability of that function can be tested
+#   with the second macro. Generally speaking, it is safe to assume that
+#   AX_HAVE_POLL would succeed if AX_HAVE_PPOLL has, but not the other way
+#   round.
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Peter Simons <simons@cryp.to>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 7
+
+AC_DEFUN([AX_HAVE_POLL], [dnl
+  AC_MSG_CHECKING([for poll(2)])
+  AC_CACHE_VAL([ax_cv_have_poll], [dnl
+    AC_LINK_IFELSE([dnl
+      AC_LANG_PROGRAM(
+        [#include <poll.h>],
+        [int rc; rc = poll((struct pollfd *)(0), 0, 0);])],
+      [ax_cv_have_poll=yes],
+      [ax_cv_have_poll=no])])
+  AS_IF([test "${ax_cv_have_poll}" = "yes"],
+    [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])dnl
+
+AC_DEFUN([AX_HAVE_PPOLL], [dnl
+  AC_MSG_CHECKING([for ppoll(2)])
+  AC_CACHE_VAL([ax_cv_have_ppoll], [dnl
+    AC_LINK_IFELSE([dnl
+      AC_LANG_PROGRAM(
+        [dnl
+#include <poll.h>
+#include <signal.h>],
+        [dnl
+int rc;
+rc = poll((struct pollfd *)(0), 0, 0);
+rc = ppoll((struct pollfd *)(0), 0, (struct timespec const *)(0), (sigset_t const *)(0));])],
+      [ax_cv_have_ppoll=yes],
+      [ax_cv_have_ppoll=no])])
+  AS_IF([test "${ax_cv_have_ppoll}" = "yes"],
+    [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])
diff --git a/net.c b/net.c
index 14f7c89a7ca677c513ed583de3a9e18e127fea73..4657d75dacd697a8edffe4aa923dbb69fc1c3f85 100644 (file)
--- a/net.c
+++ b/net.c
@@ -30,6 +30,9 @@
 #include <sys/time.h>
 #include <errno.h>
 #include <fcntl.h>
+#ifdef HAVE_POLL
+#include <poll.h>
+#endif
 
 ldns_status
 ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
@@ -150,6 +153,7 @@ static int
 ldns_sock_wait(int sockfd, struct timeval timeout, int write)
 {
        int ret;
+#ifndef HAVE_POLL
 #ifndef S_SPLINT_S
        fd_set fds;
        FD_ZERO(&fds);
@@ -158,6 +162,20 @@ ldns_sock_wait(int sockfd, struct timeval timeout, int write)
                ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
        else
                ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
+#endif
+#else
+       struct pollfd pfds[2];
+
+       memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
+
+       pfds[0].fd = sockfd;
+       pfds[0].events = POLLIN|POLLERR;
+
+       if (write) {
+               pfds[0].events |= POLLOUT;
+       }
+       
+       ret = poll(pfds, 1, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
 #endif
        if(ret == 0)
                /* timeout expired */
@@ -178,30 +196,30 @@ ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen,
 
 #ifndef S_SPLINT_S
        if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, 
-                                       IPPROTO_TCP)) == -1) {
+                                       IPPROTO_TCP)) == SOCK_INVALID) {
                return 0;
        }
 #endif
-       if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
+       if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == SOCK_INVALID){
                return 0;
        }
 
        /* perform nonblocking connect, to be able to wait with select() */
        ldns_sock_nonblock(sockfd);
-       if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
+       if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
 #ifndef USE_WINSOCK
 #ifdef EINPROGRESS
                if(errno != EINPROGRESS) {
 #else
                if(1) {
 #endif
-                       close(sockfd);
+                       close_socket(sockfd);
                        return 0;
                }
 #else /* USE_WINSOCK */
                if(WSAGetLastError() != WSAEINPROGRESS &&
                        WSAGetLastError() != WSAEWOULDBLOCK) {
-                       closesocket(sockfd);
+                       close_socket(sockfd);
                        return 0;
                }
 #endif
@@ -214,11 +232,7 @@ ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen,
                socklen_t len = (socklen_t)sizeof(error);
 
                if(!ldns_sock_wait(sockfd, timeout, 1)) {
-#ifndef USE_WINSOCK
-                       close(sockfd);
-#else
-                       closesocket(sockfd);
-#endif
+                       close_socket(sockfd);
                        return 0;
                }
 
@@ -237,7 +251,7 @@ ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen,
                        continue; /* try again */
 #endif
                else if(error != 0) {
-                       close(sockfd);
+                       close_socket(sockfd);
                        /* error in errno for our user */
                        errno = error;
                        return 0;
@@ -248,7 +262,7 @@ ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen,
                else if(error == WSAEWOULDBLOCK)
                        continue;
                else if(error != 0) {
-                       closesocket(sockfd);
+                       close_socket(sockfd);
                        errno = error;
                        return 0;
                }
@@ -285,11 +299,7 @@ ldns_tcp_bgsend_from(ldns_buffer *qbin,
        }
        
        if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
-#ifndef USE_WINSOCK
-               close(sockfd);
-#else
-               closesocket(sockfd);
-#endif
+               close_socket(sockfd);
                return 0;
        }
        
@@ -324,11 +334,7 @@ ldns_tcp_send_from(uint8_t **result,  ldns_buffer *qbin,
        }
 
        answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
-#ifndef USE_WINSOCK
-       close(sockfd);
-#else
-       closesocket(sockfd);
-#endif
+       close_socket(sockfd);
 
        if (*answer_size == 0) {
                /* oops */
@@ -387,11 +393,7 @@ ldns_udp_bgsend_from(ldns_buffer *qbin,
        }
 
        if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
-#ifndef USE_WINSOCK
-               close(sockfd);
-#else
-               closesocket(sockfd);
-#endif
+               close_socket(sockfd);
                return 0;
        }
        return sockfd;
@@ -422,11 +424,7 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
 
        /* wait for an response*/
        if(!ldns_sock_wait(sockfd, timeout, 0)) {
-#ifndef USE_WINSOCK
-               close(sockfd);
-#else
-                closesocket(sockfd);
-#endif
+               close_socket(sockfd);
                return LDNS_STATUS_NETWORK_ERR;
        }
 
@@ -436,11 +434,7 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
         ldns_sock_nonblock(sockfd);
 
        answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
-#ifndef USE_WINSOCK
-       close(sockfd);
-#else
-        closesocket(sockfd);
-#endif
+       close_socket(sockfd);
 
        if (*answer_size == 0) {
                /* oops */
@@ -892,7 +886,7 @@ ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class c
          * @hostname is used */
         for (ns_i = 0;
              ns_i < ldns_resolver_nameserver_count(resolver) &&
-             resolver->_socket == 0;
+             resolver->_socket == SOCK_INVALID;
              ns_i++) {
                if (ns != NULL) {
                        LDNS_FREE(ns);
@@ -924,7 +918,7 @@ ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class c
                                ldns_resolver_timeout(resolver));
        }
 
-       if (resolver->_socket == 0) {
+       if (resolver->_socket == SOCK_INVALID) {
                ldns_pkt_free(query);
                LDNS_FREE(ns);
                return LDNS_STATUS_NETWORK_ERR;
@@ -939,11 +933,7 @@ ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class c
                if (status != LDNS_STATUS_OK) {
                        /* to prevent problems on subsequent calls to 
                         * ldns_axfr_start we have to close the socket here! */
-#ifndef USE_WINSOCK
-                       close(resolver->_socket);
-#else
-                       closesocket(resolver->_socket);
-#endif
+                       close_socket(resolver->_socket);
                        resolver->_socket = 0;
 
                        ldns_pkt_free(query);
@@ -961,12 +951,8 @@ ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class c
         if(!query_wire) {
                 ldns_pkt_free(query);
                 LDNS_FREE(ns);
-#ifndef USE_WINSOCK
-               close(resolver->_socket);
-#else
-               closesocket(resolver->_socket);
-#endif
-               resolver->_socket = 0;
+
+               close_socket(resolver->_socket);
 
                 return LDNS_STATUS_MEM_ERR;
         }
@@ -978,11 +964,7 @@ ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class c
 
                /* to prevent problems on subsequent calls to ldns_axfr_start
                 * we have to close the socket here! */
-#ifndef USE_WINSOCK
-               close(resolver->_socket);
-#else
-               closesocket(resolver->_socket);
-#endif
+               close_socket(resolver->_socket);
                resolver->_socket = 0;
 
                 return status;
@@ -997,12 +979,8 @@ ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class c
                /* to prevent problems on subsequent calls to ldns_axfr_start
                 * we have to close the socket here! */
 
-#ifndef USE_WINSOCK
-               close(resolver->_socket);
-#else
-               closesocket(resolver->_socket);
-#endif
-               resolver->_socket = 0;
+
+               close_socket(resolver->_socket);
 
                 return LDNS_STATUS_NETWORK_ERR;
         }
index 9c523317be5b5a27481c5e2fdf45cc3efe99f39a..e09b577f567a493110810c9d2cee68fdb4bf3709 100644 (file)
@@ -650,9 +650,7 @@ ldns_resolver_new(void)
        r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
        r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
 
-       /* TODO: fd=0 is actually a valid socket (stdin),
-           replace with -1 */
-       r->_socket = 0;
+       r->_socket = -1;
        r->_axfr_soa_count = 0;
        r->_axfr_i = 0;
        r->_cur_axfr_pkt = NULL;
@@ -1042,6 +1040,8 @@ ldns_resolver_deep_free(ldns_resolver *res)
        size_t i;
 
        if (res) {
+               close_socket(res->_socket);
+
                if (res->_searchlist) {
                        for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
                                ldns_rdf_deep_free(res->_searchlist[i]);
@@ -1441,7 +1441,7 @@ ldns_axfr_next(ldns_resolver *resolver)
        ldns_status status;
 
        /* check if start() has been called */
-       if (!resolver || resolver->_socket == 0) {
+       if (!resolver || resolver->_socket == -1) {
                return NULL;
        }
 
@@ -1458,12 +1458,9 @@ ldns_axfr_next(ldns_resolver *resolver)
                if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
                        resolver->_axfr_soa_count++;
                        if (resolver->_axfr_soa_count >= 2) {
-#ifndef USE_WINSOCK
-                               close(resolver->_socket);
-#else
-                               closesocket(resolver->_socket);
-#endif
-                               resolver->_socket = 0;
+
+                               close_socket(resolver->_socket);
+
                                ldns_pkt_free(resolver->_cur_axfr_pkt);
                                resolver->_cur_axfr_pkt = NULL;
                        }
@@ -1488,12 +1485,8 @@ ldns_axfr_next(ldns_resolver *resolver)
                        /* we must now also close the socket, otherwise subsequent uses of the
                           same resolver structure will fail because the link is still open or
                           in an undefined state */
-#ifndef USE_WINSOCK
-                       close(resolver->_socket);
-#else
-                       closesocket(resolver->_socket);
-#endif
-                       resolver->_socket = 0;
+
+                       close_socket(resolver->_socket);
 
                        return NULL;
                } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
@@ -1514,12 +1507,8 @@ ldns_axfr_next(ldns_resolver *resolver)
                        /* we must now also close the socket, otherwise subsequent uses of the
                           same resolver structure will fail because the link is still open or
                           in an undefined state */
-#ifndef USE_WINSOCK
-                       close(resolver->_socket);
-#else
-                       closesocket(resolver->_socket);
-#endif
-                       resolver->_socket = 0;
+
+                       close_socket(resolver->_socket);
 
                        return NULL;
                } else {