]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Windows handle leakage fixes: closesocket or else the networkstack leaks handles...
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 29 Apr 2009 15:23:08 +0000 (15:23 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 29 Apr 2009 15:23:08 +0000 (15:23 +0000)
git-svn-id: file:///svn/unbound/trunk@1622 be551aaa-1e26-0410-a405-d3ace91eadb9

12 files changed:
daemon/remote.c
doc/CREDITS
doc/Changelog
services/listen_dnsport.c
services/outside_network.c
smallapp/unbound-control.c
testcode/delayer.c
testcode/perf.c
testcode/streamtcp.c
util/locks.c
util/locks.h
util/netevent.c

index 4689bd4891694d577a47cad8123c76fba33530c1..b5bfddfe2484415a8ab4c7a5c86bb99defb8b02e 100644 (file)
@@ -284,7 +284,11 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
        /* alloc */
        n = (struct listen_port*)calloc(1, sizeof(*n));
        if(!n) {
+#ifndef USE_WINSOCK
                close(fd);
+#else
+               closesocket(fd);
+#endif
                log_err("out of memory");
                return 0;
        }
@@ -376,7 +380,12 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
        if(rc->active >= rc->max_active) {
                log_warn("drop incoming remote control: too many connections");
                comm_point_stop_listening(c);
+       close_exit:
+#ifndef USE_WINSOCK
                close(newfd);
+#else
+               closesocket(newfd);
+#endif
                return 0;
        }
 
@@ -384,17 +393,15 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
        n = (struct rc_state*)calloc(1, sizeof(*n));
        if(!n) {
                log_err("out of memory");
-               close(newfd);
-               return 0;
+               goto close_exit;
        }
        /* start in reading state */
        n->c = comm_point_create_raw(rc->worker->base, newfd, 0, 
                &remote_control_callback, n);
        if(!n->c) {
                log_err("out of memory");
-               close(newfd);
                free(n);
-               return 0;
+               goto close_exit;
        }
        log_addr(VERB_QUERY, "new control connection from", &addr, addrlen);
        n->c->do_not_close = 0;
@@ -406,18 +413,16 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
        n->ssl = SSL_new(rc->ctx);
        if(!n->ssl) {
                log_crypto_err("could not SSL_new");
-               close(newfd);
                free(n);
-               return 0;
+               goto close_exit;
        }
        SSL_set_accept_state(n->ssl);
         (void)SSL_set_mode(n->ssl, SSL_MODE_AUTO_RETRY);
        if(!SSL_set_fd(n->ssl, newfd)) {
                log_crypto_err("could not SSL_set_fd");
-               close(newfd);
                SSL_free(n->ssl);
                free(n);
-               return 0;
+               goto close_exit;
        }
 
        n->rc = rc;
index 83b250de5e1050029c9f847cb2e010572ffd60b2..e212f75d81c2aed6a30606a2b8cf4ff690b40aee 100644 (file)
@@ -14,3 +14,4 @@ Jakob Schlyter - for advice on secure settings, random numbers and blacklists.
 Ondřej Surý - running coverity analysis tool on 0.9 dev version.
 Alexander Gall - multihomed, anycast testing of unbound resolver server.
 Zdenek Vasicek and Marek Vavrusa - python module.
+Brett Carr - windows beta testing.
index fb21cd487db48788cc276c76fe949de2ff0e0f08..fd436834b6919a1a016a5aa4a145dcbe9441dd93 100644 (file)
@@ -1,3 +1,10 @@
+29 April 2009: Wouter
+       - Thanks to Brett Carr, caught windows resource leak, use 
+         closesocket() and not close() on sockets or else the network stack
+         starts to leak handles.
+       - Removed usage of windows Mutex because windows cannot handle enough
+         mutexes open.  Provide own mutex implementation using primitives.
+
 28 April 2009: Wouter
        - created svn tag for 1.3.0.
 
index 3171c433c95dc26ed38f7d0cd9eca85cd6d72c9f..a82fa48c83874a51d0db38f2dd8666f5c2057ad9 100644 (file)
@@ -126,12 +126,13 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
 #ifndef USE_WINSOCK
                                log_err("setsockopt(..., IPV6_V6ONLY"
                                        ", ...) failed: %s", strerror(errno));
+                               close(s);
 #else
                                log_err("setsockopt(..., IPV6_V6ONLY"
                                        ", ...) failed: %s", 
                                        wsa_strerror(WSAGetLastError()));
+                               closesocket(s);
 #endif
-                               close(s);
                                *noproto = 0;
                                *inuse = 0;
                                return -1;
@@ -152,12 +153,13 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
 #ifndef USE_WINSOCK
                        log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
                                "...) failed: %s", strerror(errno));
+                       close(s);
 #else
                        log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
                                "...) failed: %s", 
                                wsa_strerror(WSAGetLastError()));
+                       closesocket(s);
 #endif
-                       close(s);
                        *noproto = 0;
                        *inuse = 0;
                        return -1;
@@ -175,19 +177,24 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
                else if(errno != EADDRINUSE)
                        log_err("can't bind socket: %s", strerror(errno));
 #endif
+               close(s);
 #else /* USE_WINSOCK */
                if(WSAGetLastError() != WSAEADDRINUSE &&
                        WSAGetLastError() != WSAEADDRNOTAVAIL)
                        log_err("can't bind socket: %s", 
                                wsa_strerror(WSAGetLastError()));
+               closesocket(s);
 #endif
-               close(s);
                return -1;
        }
        if(!fd_set_nonblock(s)) {
                *noproto = 0;
                *inuse = 0;
+#ifndef USE_WINSOCK
                close(s);
+#else
+               closesocket(s);
+#endif
                return -1;
        }
        return s;
@@ -426,7 +433,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                if(!set_recvpktinfo(s, hints->ai_family))
                        return 0;
                if(!port_insert(list, s, listen_type_udpancil)) {
+#ifndef USE_WINSOCK
                        close(s);
+#else
+                       closesocket(s);
+#endif
                        return 0;
                }
        } else if(do_udp) {
@@ -440,7 +451,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                        return 0;
                }
                if(!port_insert(list, s, listen_type_udp)) {
+#ifndef USE_WINSOCK
                        close(s);
+#else
+                       closesocket(s);
+#endif
                        return 0;
                }
        }
@@ -454,7 +469,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                        return 0;
                }
                if(!port_insert(list, s, listen_type_tcp)) {
+#ifndef USE_WINSOCK
                        close(s);
+#else
+                       closesocket(s);
+#endif
                        return 0;
                }
        }
@@ -661,8 +680,13 @@ void listening_ports_free(struct listen_port* list)
        struct listen_port* nx;
        while(list) {
                nx = list->next;
-               if(list->fd != -1)
+               if(list->fd != -1) {
+#ifndef USE_WINSOCK
                        close(list->fd);
+#else
+                       closesocket(list->fd);
+#endif
+               }
                free(list);
                list = nx;
        }
index d2aa8107ddb6d17fb3e83f056cf4653cf299818f..34cc6db3e8c5170f980c5515e040281f4f0c52e5 100644 (file)
@@ -162,12 +162,13 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
                if(1) {
 #endif
                        log_err("outgoing tcp: connect: %s", strerror(errno));
+                       close(s);
 #else /* USE_WINSOCK */
                if(WSAGetLastError() != WSAEINPROGRESS &&
                        WSAGetLastError() != WSAEWOULDBLOCK) {
+                       closesocket(s);
 #endif
                        log_addr(0, "failed address", &w->addr, w->addrlen);
-                       close(s);
                        return 0;
                }
        }
index 9cfd46a24bb0c110ae46b4271fc570e4b3adfbe5..75eeb5788dbfdb2874aeafa803725c512c8e3122 100644 (file)
@@ -302,7 +302,11 @@ go(const char* cfgfile, char* svr, int argc, char* argv[])
        ret = go_cmd(ssl, argc, argv);
 
        SSL_free(ssl);
+#ifndef USE_WINSOCK
        close(fd);
+#else
+       closesocket(fd);
+#endif
        SSL_CTX_free(ctx);
        config_delete(cfg);
        return ret;
index 9ed7ca2e5c45f394decb0582038762ed7650bad2..3bc75e8caa3241f7994ea00dd58e55711a119aae 100644 (file)
@@ -542,9 +542,15 @@ tcp_proxy_delete(struct tcp_proxy* p)
                free(s);
                s = sn;
        }
+#ifndef USE_WINSOCK
        close(p->client_s);
        if(p->server_s != -1)
                close(p->server_s);
+#else
+       closesocket(p->client_s);
+       if(p->server_s != -1)
+               closesocket(p->server_s);
+#endif
        free(p);
 }
 
@@ -593,14 +599,16 @@ service_tcp_listen(int s, fd_set* rorig, int* max, struct tcp_proxy** proxies,
 #ifndef USE_WINSOCK
                if(errno != EINPROGRESS) {
                        log_err("tcp connect: %s", strerror(errno));
+                       close(p->server_s);
+                       close(p->client_s);
 #else
                if(WSAGetLastError() != WSAEWOULDBLOCK &&
                        WSAGetLastError() != WSAEINPROGRESS) {
                        log_err("tcp connect: %s", 
                                wsa_strerror(WSAGetLastError()));
+                       closesocket(p->server_s);
+                       closesocket(p->client_s);
 #endif
-                       close(p->server_s);
-                       close(p->client_s);
                        free(p);
                        return;
                }
@@ -753,7 +761,11 @@ service_tcp_relay(struct tcp_proxy** tcp_proxies, struct timeval* now,
                        log_addr(1, "read tcp answer", &p->addr, p->addr_len);
                        if(!tcp_relay_read(p->server_s, &p->answerlist, 
                                &p->answerlast, now, delay, pkt)) {
+#ifndef USE_WINSOCK
                                close(p->server_s);
+#else
+                               closesocket(p->server_s);
+#endif
                                FD_CLR(FD_SET_T p->server_s, worig);
                                FD_CLR(FD_SET_T p->server_s, rorig);
                                p->server_s = -1;
@@ -881,7 +893,11 @@ proxy_list_clear(struct proxy* p)
                        "%u returned\n", i++, from, port, (int)p->numreuse+1,
                        (unsigned)p->numwait, (unsigned)p->numsent, 
                        (unsigned)p->numreturn);
+#ifndef USE_WINSOCK
                close(p->s);
+#else
+               closesocket(p->s);
+#endif
                free(p);
                p = np;
        }
@@ -1083,8 +1099,13 @@ service(const char* bind_str, int bindport, const char* serv_str,
 
        /* cleanup */
        verbose(1, "cleanup");
+#ifndef USE_WINSOCK
        close(s);
        close(listen_s);
+#else
+       closesocket(s);
+       closesocket(listen_s);
+#endif
        ldns_buffer_free(pkt);
        ring_delete(ring);
 }
index feb2b4ba6e0d9b24a15663052a2e204ff47630f3..8ac62bf4af190d5da73fa0aa0c7fa2d12249c24c 100644 (file)
@@ -253,7 +253,11 @@ perffree(struct perfinfo* info)
        if(!info) return;
        if(info->io) {
                for(i=0; i<info->io_num; i++) {
+#ifndef USE_WINSOCK
                        close(info->io[i].fd);
+#else
+                       closesocket(info->io[i].fd);
+#endif
                }
                free(info->io);
        }
index b687d1c9ef8e6a5bde9ab2ff43f0a7b1cae646b4..838fef6e07e6e421af68460aea23d8a8a102e697 100644 (file)
@@ -225,7 +225,11 @@ send_em(const char* svr, int udp, int noanswer, int num, char** qs)
                        recv_one(fd, udp, buf);
        }
 
+#ifndef USE_WINSOCK
        close(fd);
+#else
+       closesocket(fd);
+#endif
        ldns_buffer_free(buf);
        printf("orderly exit\n");
 }
index 3f58e92d088463b848228a4d6da963ec838821d2..8a90bc08953ae6d31c1cf56521044f23845742a6 100644 (file)
@@ -165,41 +165,32 @@ static void log_win_err(const char* str, DWORD err)
 
 void lock_basic_init(lock_basic_t* lock)
 {
-       *lock = CreateMutex(NULL, /* security attrs NULL, not process inherit*/
-               0,  /* false, we do not hold the lock initially */
-               NULL); /* create anonymous mutex */
-       if(*lock == NULL) {
-               log_win_err("CreateMutex failed", GetLastError());
-               fatal_exit("lock init failed");
-       }
+       /* implement own lock, because windows HANDLE as Mutex usage
+        * uses too many handles and would bog down the whole system. */
+       (void)InterlockedExchange(lock, 0);
 }
 
 void lock_basic_destroy(lock_basic_t* lock)
 {
-       if(!CloseHandle(*lock)) {
-               log_win_err("CloseHandle(Mutex) failed", GetLastError());
-       }
-       *lock = NULL;
+       (void)InterlockedExchange(lock, 0);
 }
 
 void lock_basic_lock(lock_basic_t* lock)
 {
-       DWORD ret = WaitForSingleObject(*lock, INFINITE);
-       if(ret == WAIT_FAILED) {
-               log_win_err("WaitForSingleObject(Mutex):WAIT_FAILED", 
-                       GetLastError());
-       } else if(ret == WAIT_TIMEOUT) {
-               log_win_err("WaitForSingleObject(Mutex):WAIT_TIMEOUT", 
-                       GetLastError());
+       LONG wait = 1; /* wait 1 msec at first */
+
+       while(InterlockedExchange(lock, 1)) {
+               /* if the old value was 1 then if was already locked */
+               Sleep(wait); /* wait with sleep */
+               wait *= 2;   /* exponential backoff for waiting */
        }
-       /* both WAIT_ABANDONED and WAIT_OBJECT_0 mean we have the lock */
+       /* the old value was 0, but we inserted 1, we locked it! */
 }
 
 void lock_basic_unlock(lock_basic_t* lock)
 {
-       if(!ReleaseMutex(*lock)) {
-               log_win_err("ReleaseMutex failed", GetLastError());
-       }
+       /* unlock it by inserting the value of 0. xchg for cache coherency. */
+       (void)InterlockedExchange(lock, 0);
 }
 
 void ub_thread_key_create(ub_thread_key_t* key, void* f)
index 39663ebbdb86ff4a4e080402d7b73dce5c4fd3e8..911b7ce1d80cd7018d3841fd55c3314e5ee173d3 100644 (file)
@@ -202,7 +202,7 @@ void* ub_thread_key_get(ub_thread_key_t key);
 #include <windows.h>
 
 /* Use a mutex */
-typedef HANDLE lock_rw_t;
+typedef LONG lock_rw_t;
 #define lock_rw_init(lock) lock_basic_init(lock)
 #define lock_rw_destroy(lock) lock_basic_destroy(lock)
 #define lock_rw_rdlock(lock) lock_basic_lock(lock)
@@ -210,14 +210,14 @@ typedef HANDLE lock_rw_t;
 #define lock_rw_unlock(lock) lock_basic_unlock(lock)
 
 /** the basic lock is a mutex, implemented opaquely, for error handling. */
-typedef HANDLE lock_basic_t;
+typedef LONG lock_basic_t;
 void lock_basic_init(lock_basic_t* lock);
 void lock_basic_destroy(lock_basic_t* lock);
 void lock_basic_lock(lock_basic_t* lock);
 void lock_basic_unlock(lock_basic_t* lock);
 
 /** on windows no spinlock, use mutex too. */
-typedef HANDLE lock_quick_t;
+typedef LONG lock_quick_t;
 #define lock_quick_init(lock) lock_basic_init(lock)
 #define lock_quick_destroy(lock) lock_basic_destroy(lock)
 #define lock_quick_lock(lock) lock_basic_lock(lock)
index 25215a3bb62e2af681236380c7120a95956e59ee..673aa1c0ff733d4a1809db8b3b4f8b2245623d93 100644 (file)
@@ -1397,7 +1397,11 @@ comm_point_close(struct comm_point* c)
        /* close fd after removing from event lists, or epoll.. is messed up */
        if(c->fd != -1 && !c->do_not_close) {
                verbose(VERB_ALGO, "close fd %d", c->fd);
+#ifndef USE_WINSOCK
                close(c->fd);
+#else
+               closesocket(c->fd);
+#endif
        }
        c->fd = -1;
 }
@@ -1497,8 +1501,13 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
                else    c->ev->ev.ev_events |= EV_WRITE;
        }
        if(newfd != -1) {
-               if(c->fd != -1)
+               if(c->fd != -1) {
+#ifndef USE_WINSOCK
                        close(c->fd);
+#else
+                       closesocket(c->fd);
+#endif
+               }
                c->fd = newfd;
                c->ev->ev.ev_fd = c->fd;
        }