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.

This commit is contained in:
Jardel Weyrich 2009-12-30 19:22:23 -02:00 committed by Nick Mathewson
parent 4367a33a20
commit fec66f9685

View File

@ -149,15 +149,18 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa,
int socklen) int socklen)
{ {
struct evconnlistener *listener;
evutil_socket_t fd; evutil_socket_t fd;
int on = 1; int on = 1;
int family = sa ? sa->sa_family : AF_UNSPEC; int family = sa ? sa->sa_family : AF_UNSPEC;
if (backlog == 0) if (backlog == 0)
return NULL; return NULL;
fd = socket(family, SOCK_STREAM, 0); fd = socket(family, SOCK_STREAM, 0);
if (fd == -1) if (fd == -1)
return NULL; return NULL;
if (evutil_make_socket_nonblocking(fd) < 0) { if (evutil_make_socket_nonblocking(fd) < 0) {
EVUTIL_CLOSESOCKET(fd); EVUTIL_CLOSESOCKET(fd);
return NULL; 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 void
@ -545,24 +554,24 @@ evconnlistener_new_async(struct event_base *base,
int i; int i;
if (!event_base_get_iocp(base)) if (!event_base_get_iocp(base))
return NULL; goto err;
/* XXXX duplicate code */ /* XXXX duplicate code */
if (backlog > 0) { if (backlog > 0) {
if (listen(fd, backlog) < 0) if (listen(fd, backlog) < 0)
return NULL; goto err;
} else if (backlog < 0) { } else if (backlog < 0) {
if (listen(fd, 128) < 0) if (listen(fd, 128) < 0)
return NULL; goto err;
} }
if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) { if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) {
event_sock_warn(fd, "getsockname"); event_sock_warn(fd, "getsockname");
return NULL; goto err;
} }
lev = mm_calloc(1, sizeof(struct evconnlistener_event)); lev = mm_calloc(1, sizeof(struct evconnlistener_event));
if (!lev) { if (!lev) {
event_warn("calloc"); event_warn("calloc");
return NULL; goto err;
} }
lev->base.ops = &evconnlistener_iocp_ops; lev->base.ops = &evconnlistener_iocp_ops;
lev->base.cb = cb; lev->base.cb = cb;
@ -574,7 +583,7 @@ evconnlistener_new_async(struct event_base *base,
lev->event_base = base; lev->event_base = base;
if (event_iocp_port_associate(lev->port, fd, 1) < 0) if (event_iocp_port_associate(lev->port, fd, 1) < 0)
return NULL; goto err_free_lev;
InitializeCriticalSection(&lev->lock); InitializeCriticalSection(&lev->lock);
@ -583,35 +592,34 @@ evconnlistener_new_async(struct event_base *base,
sizeof(struct accepting_socket *)); sizeof(struct accepting_socket *));
if (!lev->accepting) { if (!lev->accepting) {
event_warn("calloc"); event_warn("calloc");
mm_free(lev); goto err_delete_lock;
closesocket(fd);
return NULL;
} }
for (i = 0; i < lev->n_accepting; ++i) { for (i = 0; i < lev->n_accepting; ++i) {
lev->accepting[i] = new_accepting_socket(lev, ss.ss_family); lev->accepting[i] = new_accepting_socket(lev, ss.ss_family);
if (!lev->accepting[i]) { if (!lev->accepting[i]) {
event_warnx("Couldn't create accepting socket"); event_warnx("Couldn't create accepting socket");
mm_free(lev->accepting); goto err_free_accepting;
/* DeleteCriticalSection on lev->lock XXXX */
/* XXXX free the other elements. */
mm_free(lev);
closesocket(fd);
return NULL;
} }
if (start_accepting(lev->accepting[i]) < 0) { if (start_accepting(lev->accepting[i]) < 0) {
event_warnx("Couldn't start accepting on socket"); event_warnx("Couldn't start accepting on socket");
EnterCriticalSection(&lev->accepting[i]->lock); EnterCriticalSection(&lev->accepting[i]->lock);
free_and_unlock_accepting_socket(lev->accepting[i]); free_and_unlock_accepting_socket(lev->accepting[i]);
mm_free(lev->accepting); goto err_free_accepting;
mm_free(lev);
closesocket(fd);
DeleteCriticalSection(&lev->lock);
return NULL;
} }
} }
return &lev->base; 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 #endif