Minimize syscalls during socket creation in listener.c

This commit is contained in:
Nick Mathewson 2012-02-10 16:13:30 -05:00
parent a1c042bfe9
commit 7e9e289367

View File

@ -80,6 +80,7 @@ struct evconnlistener {
void *user_data; void *user_data;
unsigned flags; unsigned flags;
short refcnt; short refcnt;
int accept4_flags;
unsigned enabled : 1; unsigned enabled : 1;
}; };
@ -186,6 +187,10 @@ evconnlistener_new(struct event_base *base,
lev->base.flags = flags; lev->base.flags = flags;
lev->base.refcnt = 1; lev->base.refcnt = 1;
lev->base.accept4_flags = 0;
if (!(flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
lev->base.accept4_flags |= EVUTIL_SOCK_NONBLOCK;
if (flags & LEV_OPT_THREADSAFE) { if (flags & LEV_OPT_THREADSAFE) {
EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
} }
@ -193,8 +198,8 @@ evconnlistener_new(struct event_base *base,
event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST, event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST,
listener_read_cb, lev); listener_read_cb, lev);
if (!(flags & LEV_OPT_DISABLED)) if (!(flags & LEV_OPT_DISABLED))
evconnlistener_enable(&lev->base); evconnlistener_enable(&lev->base);
return &lev->base; return &lev->base;
} }
@ -208,26 +213,18 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
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;
int socktype = SOCK_STREAM | EVUTIL_SOCK_NONBLOCK;
if (backlog == 0) if (backlog == 0)
return NULL; return NULL;
fd = socket(family, SOCK_STREAM, 0); if (flags & LEV_OPT_CLOSE_ON_EXEC)
socktype |= EVUTIL_SOCK_CLOEXEC;
fd = evutil_socket(family, socktype, 0);
if (fd == -1) if (fd == -1)
return NULL; return NULL;
if (evutil_make_socket_nonblocking(fd) < 0) {
evutil_closesocket(fd);
return NULL;
}
if (flags & LEV_OPT_CLOSE_ON_EXEC) {
if (evutil_make_socket_closeonexec(fd) < 0) {
evutil_closesocket(fd);
return NULL;
}
}
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on)); setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on));
if (flags & LEV_OPT_REUSEABLE) { if (flags & LEV_OPT_REUSEABLE) {
evutil_make_listen_socket_reuseable(fd); evutil_make_listen_socket_reuseable(fd);
@ -389,7 +386,7 @@ listener_read_cb(evutil_socket_t fd, short what, void *p)
#else #else
socklen_t socklen = sizeof(ss); socklen_t socklen = sizeof(ss);
#endif #endif
evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen); evutil_socket_t new_fd = evutil_accept4(fd, (struct sockaddr*)&ss, &socklen, lev->accept4_flags);
if (new_fd < 0) if (new_fd < 0)
break; break;
if (socklen == 0) { if (socklen == 0) {
@ -399,9 +396,6 @@ listener_read_cb(evutil_socket_t fd, short what, void *p)
continue; continue;
} }
if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
evutil_make_socket_nonblocking(new_fd);
if (lev->cb == NULL) { if (lev->cb == NULL) {
UNLOCK(lev); UNLOCK(lev);
return; return;