mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 04:50:37 -04:00
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:
parent
4367a33a20
commit
fec66f9685
52
listener.c
52
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,
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user