From: Maciej Soltysiak Date: Mon, 13 Oct 2014 15:28:14 +0000 (+0200) Subject: Provide support for SO_REUSEPORT through LEV_OPT_REUSABLE_PORT X-Git-Tag: release-2.1.5-beta~19^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b625361a6a2b2bc4ba1c71a1d6dc89f5e2b4d9e0;p=libevent Provide support for SO_REUSEPORT through LEV_OPT_REUSABLE_PORT --- diff --git a/evutil.c b/evutil.c index df93e67f..3d72e403 100644 --- a/evutil.c +++ b/evutil.c @@ -367,6 +367,20 @@ evutil_make_listen_socket_reuseable(evutil_socket_t sock) #endif } +int +evutil_make_listen_socket_reuseable_port(evutil_socket_t sock) +{ +#if defined __linux__ && defined(SO_REUSEPORT) + int one = 1; + /* REUSEPORT on Linux 3.9+ means, "Multiple servers (processes or + * threads) can bind to the same port if they each set the option. */ + return setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*) &one, + (ev_socklen_t)sizeof(one)); +#else + return 0; +#endif +} + int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock) { diff --git a/include/event2/listener.h b/include/event2/listener.h index 8c77803d..84b4da05 100644 --- a/include/event2/listener.h +++ b/include/event2/listener.h @@ -88,6 +88,15 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *); * to use the option before it is actually bound. */ #define LEV_OPT_DEFERRED_ACCEPT (1u<<6) +/** Flag: Indicates that we ask to allow multiple servers (processes or + * threads) to bind to the same port if they each set the option. + * + * SO_REUSEPORT is what most people would expect SO_REUSEADDR to be, however + * SO_REUSEPORT does not imply SO_REUSEADDR. + * + * This is only available on Linux and kernel 3.9+ + */ +#define LEV_OPT_REUSEABLE_PORT (1u<<7) /** Allocate a new evconnlistener object to listen for incoming TCP connections diff --git a/include/event2/util.h b/include/event2/util.h index 14c6a25d..62b94773 100644 --- a/include/event2/util.h +++ b/include/event2/util.h @@ -327,6 +327,19 @@ int evutil_make_socket_nonblocking(evutil_socket_t sock); EVENT2_EXPORT_SYMBOL int evutil_make_listen_socket_reuseable(evutil_socket_t sock); +/** Do platform-specific operations to make a listener port reusable. + + Specifically, we want to make sure that multiple programs which also + set the same socket option will be able to bind, listen at the same time. + + This is a feature available only to Linux 3.9+ + + @param sock The socket to make reusable + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock); + /** Do platform-specific operations as needed to close a socket upon a successful execution of one of the exec*() functions. diff --git a/listener.c b/listener.c index 3272c405..172d2927 100644 --- a/listener.c +++ b/listener.c @@ -235,6 +235,11 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, goto err; } + if (flags & LEV_OPT_REUSEABLE_PORT) { + if (evutil_make_listen_socket_reuseable_port(fd) < 0) + goto err; + } + if (flags & LEV_OPT_DEFERRED_ACCEPT) { if (evutil_make_tcp_listen_socket_deferred(fd) < 0) goto err;