From: Jardel Weyrich Date: Wed, 30 Dec 2009 21:22:23 +0000 (-0200) Subject: Improved error handling in evconnlistener_new_async(). Also keeping the fd open becau... X-Git-Tag: release-2.0.4-alpha~85 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fec66f96850b77f77f720d3983ae98fc3594f282;p=libevent Improved error handling in evconnlistener_new_async(). Also keeping the fd open because it is not opened by this function, so the caller is responsible for closing it. Additionally, since evconnlistener_new_bind() creates a socket and passes it to the function above, it required error checking to close the same socket. --- diff --git a/listener.c b/listener.c index b044d9b7..d7557f3b 100644 --- a/listener.c +++ b/listener.c @@ -149,15 +149,18 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen) { + struct evconnlistener *listener; evutil_socket_t fd; int on = 1; int family = sa ? sa->sa_family : AF_UNSPEC; if (backlog == 0) return NULL; + fd = socket(family, SOCK_STREAM, 0); if (fd == -1) return NULL; + if (evutil_make_socket_nonblocking(fd) < 0) { EVUTIL_CLOSESOCKET(fd); return NULL; @@ -182,7 +185,13 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, } } - return evconnlistener_new(base, cb, ptr, flags, backlog, fd); + listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd); + if (!listener) { + EVUTIL_CLOSESOCKET(fd); + return NULL; + } + + return listener; } void @@ -545,24 +554,24 @@ evconnlistener_new_async(struct event_base *base, int i; if (!event_base_get_iocp(base)) - return NULL; + goto err; /* XXXX duplicate code */ if (backlog > 0) { if (listen(fd, backlog) < 0) - return NULL; + goto err; } else if (backlog < 0) { if (listen(fd, 128) < 0) - return NULL; + goto err; } if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) { event_sock_warn(fd, "getsockname"); - return NULL; + goto err; } lev = mm_calloc(1, sizeof(struct evconnlistener_event)); if (!lev) { event_warn("calloc"); - return NULL; + goto err; } lev->base.ops = &evconnlistener_iocp_ops; lev->base.cb = cb; @@ -574,7 +583,7 @@ evconnlistener_new_async(struct event_base *base, lev->event_base = base; if (event_iocp_port_associate(lev->port, fd, 1) < 0) - return NULL; + goto err_free_lev; InitializeCriticalSection(&lev->lock); @@ -583,35 +592,34 @@ evconnlistener_new_async(struct event_base *base, sizeof(struct accepting_socket *)); if (!lev->accepting) { event_warn("calloc"); - mm_free(lev); - closesocket(fd); - return NULL; + goto err_delete_lock; } for (i = 0; i < lev->n_accepting; ++i) { lev->accepting[i] = new_accepting_socket(lev, ss.ss_family); if (!lev->accepting[i]) { event_warnx("Couldn't create accepting socket"); - mm_free(lev->accepting); - /* DeleteCriticalSection on lev->lock XXXX */ - /* XXXX free the other elements. */ - mm_free(lev); - closesocket(fd); - return NULL; + goto err_free_accepting; } - if (start_accepting(lev->accepting[i]) < 0) { event_warnx("Couldn't start accepting on socket"); EnterCriticalSection(&lev->accepting[i]->lock); free_and_unlock_accepting_socket(lev->accepting[i]); - mm_free(lev->accepting); - mm_free(lev); - closesocket(fd); - DeleteCriticalSection(&lev->lock); - return NULL; + goto err_free_accepting; } } return &lev->base; + +err_free_accepting: + mm_free(lev->accepting); + /* XXXX free the other elements. */ +err_delete_lock: + DeleteCriticalSection(&lev->lock); +err_free_lev: + mm_free(lev); +err: + /* Don't close the fd, it is caller's responsibility. */ + return NULL; } #endif