From: Wouter Wijngaards Date: Wed, 29 Apr 2009 15:23:08 +0000 (+0000) Subject: Windows handle leakage fixes: closesocket or else the networkstack leaks handles... X-Git-Tag: release-1.3.0~2^2~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=578c1632ce07184202d28be0bb98e5943c183dd9;p=thirdparty%2Funbound.git Windows handle leakage fixes: closesocket or else the networkstack leaks handles (for ever, even after closing the application), and use own mutex implementation (whee!). git-svn-id: file:///svn/unbound/trunk@1622 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/remote.c b/daemon/remote.c index 4689bd489..b5bfddfe2 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -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; diff --git a/doc/CREDITS b/doc/CREDITS index 83b250de5..e212f75d8 100644 --- a/doc/CREDITS +++ b/doc/CREDITS @@ -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. diff --git a/doc/Changelog b/doc/Changelog index fb21cd487..fd436834b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 3171c433c..a82fa48c8 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -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; } diff --git a/services/outside_network.c b/services/outside_network.c index d2aa8107d..34cc6db3e 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -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; } } diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index 9cfd46a24..75eeb5788 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -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; diff --git a/testcode/delayer.c b/testcode/delayer.c index 9ed7ca2e5..3bc75e8ca 100644 --- a/testcode/delayer.c +++ b/testcode/delayer.c @@ -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); } diff --git a/testcode/perf.c b/testcode/perf.c index feb2b4ba6..8ac62bf4a 100644 --- a/testcode/perf.c +++ b/testcode/perf.c @@ -253,7 +253,11 @@ perffree(struct perfinfo* info) if(!info) return; if(info->io) { for(i=0; iio_num; i++) { +#ifndef USE_WINSOCK close(info->io[i].fd); +#else + closesocket(info->io[i].fd); +#endif } free(info->io); } diff --git a/testcode/streamtcp.c b/testcode/streamtcp.c index b687d1c9e..838fef6e0 100644 --- a/testcode/streamtcp.c +++ b/testcode/streamtcp.c @@ -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"); } diff --git a/util/locks.c b/util/locks.c index 3f58e92d0..8a90bc089 100644 --- a/util/locks.c +++ b/util/locks.c @@ -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) diff --git a/util/locks.h b/util/locks.h index 39663ebbd..911b7ce1d 100644 --- a/util/locks.h +++ b/util/locks.h @@ -202,7 +202,7 @@ void* ub_thread_key_get(ub_thread_key_t key); #include /* 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) diff --git a/util/netevent.c b/util/netevent.c index 25215a3bb..673aa1c0f 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -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; }