Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement TCP Keep-Alives across most Unix-like systems #12782

Merged
merged 5 commits into from
Dec 26, 2023

Conversation

panjf2000
Copy link
Contributor

@panjf2000 panjf2000 commented Nov 20, 2023

TCP Keep-Alives

TCP Keep-Alives provides a way to detect whether a TCP connection is alive or dead, which can be useful for reducing system resources by cleaning up dead connections.

There is full support of TCP Keep-Alives on Linux and partial support on macOS in redis at present.

This PR intends to complete the rest.

Unix-like OS's support

TCP_KEEPIDLE, TCP_KEEPINTVL, and TCP_KEEPCNT are not included in the POSIX standard for setsockopts, while these three socket options are widely available on most Unix-like systems and Windows.

References

Mac OS

In earlier versions, macOS only supported setting TCP_KEEPALIVE (the equivalent of TCP_KEEPIDLE on other platforms), but since macOS 10.8 it has supported TCP_KEEPINTVL and TCP_KEEPCNT.

Check out this mailing list and the source code for more details.

Solaris

Solaris claimed it supported the TCP-Alives mechanism, but TCP_KEEPIDLE, TCP_KEEPINTVL, and TCP_KEEPCNT were not available on Solaris until the latest version 11.4. Therefore, we need to simulate the TCP-Alives mechanism on other platforms via TCP_KEEPALIVE_THRESHOLD + TCP_KEEPALIVE_ABORT_THRESHOLD.

@panjf2000 panjf2000 force-pushed the anet-keepalive branch 3 times, most recently from 9d856b9 to ed29b3a Compare November 20, 2023 05:07
@panjf2000 panjf2000 changed the title Implement TCP keep-alive across most Unix-like systems Implement TCP Keep-Alives across most Unix-like systems Nov 20, 2023
src/anet.c Outdated Show resolved Hide resolved
Copy link
Collaborator

@hpatro hpatro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we test and verify this functionality?

@hpatro hpatro requested a review from oranagra November 21, 2023 19:06
@panjf2000
Copy link
Contributor Author

panjf2000 commented Nov 22, 2023

How did we test and verify this functionality?

It seems that this function has never been "verified" in any testable way, just like else functions in anet.c.
Besides, testing TCP-Alives can be tricky because it's necessarily timing-sensitive.

cc @oranagra

Copy link
Contributor

@zuiderkwast zuiderkwast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only new code is for Solaris, right? The rest of the code is just moved and renamed variables. We usually want to avoid small changes like moving code and renaming variables. Can you avoid those changes and make the diff as small as possible?

@panjf2000
Copy link
Contributor Author

The only new code is for Solaris, right? The rest of the code is just moved and renamed variables. We usually want to avoid small changes like moving code and renaming variables. Can you avoid those changes and make the diff as small as possible?

Actually, it's intended to restructure the code and make it more generic to avoid multiple OS-specific macros, that way we don't have to do something like #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || ...; #elif defined(__APPLE__) ...

@panjf2000
Copy link
Contributor Author

Do you have a minute for this PR?
@oranagra

@panjf2000
Copy link
Contributor Author

Ping @oranagra

1 similar comment
@panjf2000
Copy link
Contributor Author

Ping @oranagra

@panjf2000
Copy link
Contributor Author

panjf2000 commented Dec 21, 2023

It's been a month, what is holding this back? I'm so confused with the zero response from the maintainer at present. Is this feature not worth the effort? Or this PR will get reviewed, just need to wait a little longer? I'll take any response @oranagra

@enjoy-binbin
Copy link
Collaborator

@panjf2000 sorry for the late reply. I believe oran must be too busy and missed the notifications.
I will ping him privately next week to get his attention.

@panjf2000
Copy link
Contributor Author

@panjf2000 sorry for the late reply. I believe oran must be too busy and missed the notifications. I will ping him privately next week to get his attention.

Thanks!

Copy link
Member

@oranagra oranagra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for the delay.
indeed i'm overwhelmed by notifications.

src/anet.c Show resolved Hide resolved
@oranagra oranagra merged commit 1aa633d into redis:unstable Dec 26, 2023
13 checks passed
@oranagra oranagra added the release-notes indication that this issue needs to be mentioned in the release notes label Dec 26, 2023
@panjf2000 panjf2000 deleted the anet-keepalive branch December 26, 2023 16:50
oranagra pushed a commit that referenced this pull request Jan 8, 2024
…Alive (#12914)

This is a follow-up PR for #12782, in which we introduced nested
preprocessor directives for TCP keep-alive on Solaris and added
redundant indentation for code. Besides, it could result in unreachable
code due to the lack of `#else` on the latest Solaris 11.4 where
`TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` are available. As a
result, this PR does three main things:

- To eliminate the redundant indention for C code in nested preprocessor
directives
- To add `#else` directives and move `TCP_KEEPALIVE_THRESHOLD` +
`TCP_KEEPALIVE_ABORT_THRESHOLD` settings under it, avoid unreachable
code and compiler warnings when `#if defined(TCP_KEEPIDLE) &&
defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)` is met on Solaris 11.4
- To remove a few trailing whitespace in comments
roggervalf pushed a commit to roggervalf/redis that referenced this pull request Feb 11, 2024
## TCP Keep-Alives

[TCP
Keep-Alives](https://datatracker.ietf.org/doc/html/rfc9293#name-tcp-keep-alives)
provides a way to detect whether a TCP connection is alive or dead,
which can be useful for reducing system resources by cleaning up dead
connections.

There is full support of TCP Keep-Alives on Linux and partial support on
macOS in `redis` at present.

This PR intends to complete the rest.

## Unix-like OS's support

`TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` are not included in
the POSIX standard for `setsockopts`, while these three socket options
are widely available on most Unix-like systems and Windows.

### References

- [AIX](https://www.ibm.com/support/pages/ibm-aix-tcp-keepalive-probes)
- [DragonflyBSD](https://man.dragonflybsd.org/?command=tcp&section=4)
- [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=tcp)
-
[HP-UX](https://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/TCP.7P.html)
- [illumos](https://illumos.org/man/4P/tcp)
- [Linux](https://man7.org/linux/man-pages/man7/tcp.7.html)
- [NetBSD](https://man.netbsd.org/NetBSD-8.0/tcp.4)
-
[Windows](https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options)

### Mac OS

In earlier versions, macOS only supported setting `TCP_KEEPALIVE` (the
equivalent of `TCP_KEEPIDLE` on other platforms), but since macOS 10.8
it has supported `TCP_KEEPINTVL` and `TCP_KEEPCNT`.

Check out [this mailing
list](https://lists.apple.com/archives/macnetworkprog/2012/Jul/msg00005.html)
and [the source
code](https://github.com/apple/darwin-xnu/blob/main/bsd/netinet/tcp.h#L215-L230)
for more details.

### Solaris

Solaris claimed it supported the TCP-Alives mechanism, but
`TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` were not available on
Solaris until the latest version 11.4. Therefore, we need to simulate
the TCP-Alives mechanism on other platforms via
`TCP_KEEPALIVE_THRESHOLD` + `TCP_KEEPALIVE_ABORT_THRESHOLD`.

- [Solaris
11.3](https://docs.oracle.com/cd/E86824_01/html/E54777/tcp-7p.html)
- [Solaris
11.4](https://docs.oracle.com/cd/E88353_01/html/E37851/tcp-4p.html)

---------

Co-authored-by: Oran Agra <oran@redislabs.com>
roggervalf pushed a commit to roggervalf/redis that referenced this pull request Feb 11, 2024
…Alive (redis#12914)

This is a follow-up PR for redis#12782, in which we introduced nested
preprocessor directives for TCP keep-alive on Solaris and added
redundant indentation for code. Besides, it could result in unreachable
code due to the lack of `#else` on the latest Solaris 11.4 where
`TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` are available. As a
result, this PR does three main things:

- To eliminate the redundant indention for C code in nested preprocessor
directives
- To add `#else` directives and move `TCP_KEEPALIVE_THRESHOLD` +
`TCP_KEEPALIVE_ABORT_THRESHOLD` settings under it, avoid unreachable
code and compiler warnings when `#if defined(TCP_KEEPIDLE) &&
defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)` is met on Solaris 11.4
- To remove a few trailing whitespace in comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-notes indication that this issue needs to be mentioned in the release notes
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

5 participants