Skip to content

Commit 24f08e1

Browse files
committed
Core: optimize TCP keepalive and implement TCP_KEEPALIVE on Darwin
For TCP keepalive mechanism, `SO_KEEPALIVE` is inherited by a accepted socket from the listening socket on most UNIX-like OS's[^1], whereas `TCP_KEEP*` options are only inherited on Linux, FreeBSD, or DragonFlyBSD[^2] [^3] [^4] [^5] [^6] [^7] [^8] This PR does two things: 1. Set TCP keepalive options on accepted sockets instead of the listening socket when the OS is not one of Linux, FreeBSD, or DragonFlyBSD. 2. In earlier versions, macOS only supported setting `TCP_KEEPALIVE` in place of `TCP_KEEPIDLE`, but macOS has supported `TCP_KEEPINTVL` and `TCP_KEEPCNT` since 10.8 in 2012[^9] [^10] [^11]. Use `TCP_KEEPALIVE` on macOS. Fixes #336 [^1]: https://unpbook.com/ [^2]: https://man7.org/linux/man-pages/man7/tcp.7.html [^3]: https://man.freebsd.org/cgi/man.cgi?query=tcp [^4]: https://man.dragonflybsd.org/?command=tcp&section=4 [^5]: https://man.netbsd.org/tcp.4 [^6]: https://docs.oracle.com/cd/E88353_01/html/E37851/tcp-4p.html [^7]: https://smartos.org/man/4P/tcp [^8]: https://groups.google.com/g/erlang-programming/c/vCI3PCZuj9k/m/PKnFAL5ZBQAJ [^9]: https://lists.apple.com/archives/macnetworkprog/2012/Jul/msg00005.html [^10]: https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/netinet/tcp.h#L215-L230 [^11]: https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/netinet/tcp.h#L226-L241
1 parent f354250 commit 24f08e1

File tree

4 files changed

+98
-14
lines changed

4 files changed

+98
-14
lines changed

auto/os/darwin

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,19 @@ ngx_feature_libs=
118118
ngx_feature_test="int32_t lock = 0;
119119
if (!OSAtomicCompareAndSwap32Barrier(0, 1, &lock)) return 1"
120120
. auto/feature
121+
122+
123+
# TCP keepalive
124+
125+
ngx_feature="TCP_KEEPALIVE"
126+
ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
127+
ngx_feature_run=no
128+
ngx_feature_incs="#include <sys/socket.h>
129+
#include <netinet/in.h>
130+
#include <netinet/tcp.h>"
131+
ngx_feature_path=
132+
ngx_feature_libs=
133+
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPALIVE, NULL, 0);
134+
setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
135+
setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
136+
. auto/feature

auto/unix

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -508,18 +508,20 @@ ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_DEFER_ACCEPT, NULL, 0)"
508508
. auto/feature
509509

510510

511-
ngx_feature="TCP_KEEPIDLE"
512-
ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
513-
ngx_feature_run=no
514-
ngx_feature_incs="#include <sys/socket.h>
515-
#include <netinet/in.h>
516-
#include <netinet/tcp.h>"
517-
ngx_feature_path=
518-
ngx_feature_libs=
519-
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
520-
setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
521-
setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
522-
. auto/feature
511+
if [ -z "$NGX_HAVE_KEEPALIVE_TUNABLE" ]; then
512+
ngx_feature="TCP_KEEPIDLE"
513+
ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
514+
ngx_feature_run=no
515+
ngx_feature_incs="#include <sys/socket.h>
516+
#include <netinet/in.h>
517+
#include <netinet/tcp.h>"
518+
ngx_feature_path=
519+
ngx_feature_libs=
520+
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
521+
setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
522+
setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
523+
. auto/feature
524+
fi
523525

524526

525527
ngx_feature="TCP_FASTOPEN"

src/core/ngx_connection.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -763,8 +763,10 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
763763
}
764764
}
765765

766-
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
767-
766+
#if (NGX_HAVE_KEEPALIVE_TUNABLE) && \
767+
(defined(__DragonFly__) || \
768+
defined(__FreeBSD__) || \
769+
defined(__linux__))
768770
if (ls[i].keepidle) {
769771
value = ls[i].keepidle;
770772

src/event/ngx_event_accept.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ static void ngx_close_accepted_connection(ngx_connection_t *c);
2020
void
2121
ngx_event_accept(ngx_event_t *ev)
2222
{
23+
int sockval;
2324
socklen_t socklen;
2425
ngx_err_t err;
2526
ngx_log_t *log;
@@ -156,6 +157,69 @@ ngx_event_accept(ngx_event_t *ev)
156157
(void) ngx_atomic_fetch_add(ngx_stat_active, 1);
157158
#endif
158159

160+
#if (NGX_HAVE_KEEPALIVE_TUNABLE) && \
161+
!defined(__DragonFly__) && \
162+
!defined(__FreeBSD__) && \
163+
!defined(__linux__)
164+
if (ls->keepidle) {
165+
sockval = ls->keepidle;
166+
167+
#if (NGX_KEEPALIVE_FACTOR)
168+
sockval *= NGX_KEEPALIVE_FACTOR;
169+
#endif
170+
171+
#ifdef TCP_KEEPIDLE
172+
if (setsockopt(ls->fd, IPPROTO_TCP, TCP_KEEPIDLE,
173+
(const void *) &sockval, sizeof(int))
174+
== -1)
175+
{
176+
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
177+
"setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
178+
sockval, &ls->addr_text);
179+
}
180+
#elif defined(TCP_KEEPALIVE)
181+
/* The equivalent of TCP_KEEPIDLE on Darwin is TCP_KEEPALIVE. */
182+
if (setsockopt(s, IPPROTO_TCP, TCP_KEEPALIVE,
183+
(const void *) &sockval, sizeof(int))
184+
== -1)
185+
{
186+
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
187+
"setsockopt(TCP_KEEPALIVE, %d) %V failed, ignored",
188+
sockval, &ls->addr_text);
189+
}
190+
#endif
191+
}
192+
193+
if (ls->keepintvl) {
194+
sockval = ls->keepintvl;
195+
196+
#if (NGX_KEEPALIVE_FACTOR)
197+
sockval *= NGX_KEEPALIVE_FACTOR;
198+
#endif
199+
200+
if (setsockopt(ls->fd, IPPROTO_TCP, TCP_KEEPINTVL,
201+
(const void *) &sockval, sizeof(int))
202+
== -1)
203+
{
204+
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
205+
"setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
206+
sockval, &ls->addr_text);
207+
}
208+
}
209+
210+
if (ls->keepcnt) {
211+
if (setsockopt(ls->fd, IPPROTO_TCP, TCP_KEEPCNT,
212+
(const void *) &ls->keepcnt, sizeof(int))
213+
== -1)
214+
{
215+
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
216+
"setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
217+
ls->keepcnt, &ls->addr_text);
218+
}
219+
}
220+
221+
#endif
222+
159223
c->pool = ngx_create_pool(ls->pool_size, ev->log);
160224
if (c->pool == NULL) {
161225
ngx_close_accepted_connection(c);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy