From: Amos Jeffries Date: Sun, 1 Aug 2021 12:58:25 +0000 (+0000) Subject: Fix TCP keepalive (#853) X-Git-Tag: SQUID_6_0_1~303 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1dde46601ec02f0e9879d6d37199a1353a88c860;p=thirdparty%2Fsquid.git Fix TCP keepalive (#853) Setting TCP keep-alive flags at accept(2) time resolves issues with client sockets timing out while waiting for the ::Server handler to run. Also resolves a bug with FTP DATA connections not having keep-alive set. These connections would truncate objects if the data transfer connection paused for too long and became timed out by the network routing system. --- diff --git a/acinclude/ax_cxx_0x_types.m4 b/acinclude/ax_cxx_0x_types.m4 index 52ab37b21f..289b49f53f 100644 --- a/acinclude/ax_cxx_0x_types.m4 +++ b/acinclude/ax_cxx_0x_types.m4 @@ -57,3 +57,22 @@ enum class testEnum { one, two, three }; [$squid_cv_have_std_underlying_type], [Define if stdlibc support std::underlying_type for enums]) ]) + +## SQUID_CXX_STD_IS_TRIVIALLY_COPYABLE +## checks whether the std::is_trivially_copyable<> trait exists +## (known to be missing in GCC until version 5.1) +AC_DEFUN([SQUID_CXX_STD_IS_TRIVIALLY_COPYABLE],[ + AC_CACHE_CHECK([whether compiler supports std::is_trivially_copyable], + [squid_cv_have_std_is_trivially_copyable],[ + AC_REQUIRE([AC_PROG_CXX]) + AC_LANG_PUSH([C++]) + AC_TRY_COMPILE([#include ], + [return std::is_trivially_copyable::value ? 1 : 0;], + [squid_cv_have_std_is_trivially_copyable=yes], + [squid_cv_have_std_is_trivially_copyable=no]) + AC_LANG_POP + ]) + SQUID_DEFINE_BOOL([HAVE_STD_IS_TRIVIALLY_COPYABLE], + [$squid_cv_have_std_is_trivially_copyable], + [Define if stdlibc support std::is_trivially_copyable]) +]) diff --git a/configure.ac b/configure.ac index 3ce45e1f36..dcdfa45cd7 100644 --- a/configure.ac +++ b/configure.ac @@ -2900,6 +2900,7 @@ AC_CHECK_SIZEOF(size_t) dnl Some C++11 types we try to use AX_CXX_TYPE_UNIFORM_DISTRIBUTIONS SQUID_CXX_STD_UNDERLYING_TYPE +SQUID_CXX_STD_IS_TRIVIALLY_COPYABLE dnl On Solaris 9 x86, gcc may includes a "fixed" set of old system include files dnl that is incompatible with the updated Solaris header files. diff --git a/src/anyp/PortCfg.cc b/src/anyp/PortCfg.cc index 95d12be739..6a86396b5c 100644 --- a/src/anyp/PortCfg.cc +++ b/src/anyp/PortCfg.cc @@ -42,7 +42,6 @@ AnyP::PortCfg::PortCfg() : workerQueues(false), listenConn() { - memset(&tcp_keepalive, 0, sizeof(tcp_keepalive)); } AnyP::PortCfg::~PortCfg() diff --git a/src/anyp/PortCfg.h b/src/anyp/PortCfg.h index 7c46a85b56..5cffac33a5 100644 --- a/src/anyp/PortCfg.h +++ b/src/anyp/PortCfg.h @@ -14,6 +14,7 @@ #include "anyp/TrafficMode.h" #include "base/CodeContext.h" #include "comm/Connection.h" +#include "comm/Tcp.h" #include "sbuf/SBuf.h" #include "security/ServerOptions.h" @@ -53,12 +54,7 @@ public: int disable_pmtu_discovery; bool workerQueues; ///< whether listening queues should be worker-specific - struct { - unsigned int idle; - unsigned int interval; - unsigned int timeout; - bool enabled; - } tcp_keepalive; + Comm::TcpKeepAlive tcp_keepalive; /** * The listening socket details. diff --git a/src/client_side.cc b/src/client_side.cc index 8e1659a028..7da4c82925 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -2328,9 +2328,6 @@ httpAccept(const CommAcceptCbParams ¶ms) debugs(33, 4, params.conn << ": accepted"); fd_note(params.conn->fd, "client http connect"); - if (s->tcp_keepalive.enabled) - commSetTcpKeepalive(params.conn->fd, s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout); - // Socket is ready, setup the connection manager to start using it auto *srv = Http::NewServer(xact); AsyncJob::Start(srv); // usually async-calls readSomeData() @@ -2531,10 +2528,6 @@ httpsAccept(const CommAcceptCbParams ¶ms) debugs(33, 4, HERE << params.conn << " accepted, starting SSL negotiation."); fd_note(params.conn->fd, "client https connect"); - if (s->tcp_keepalive.enabled) { - commSetTcpKeepalive(params.conn->fd, s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout); - } - // Socket is ready, setup the connection manager to start using it auto *srv = Https::NewServer(xact); AsyncJob::Start(srv); // usually async-calls postHttpsAccept() diff --git a/src/comm.cc b/src/comm.cc index 60d4f1b39f..dba7c60e9c 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1142,41 +1142,6 @@ commSetTcpNoDelay(int fd) #endif -void -commSetTcpKeepalive(int fd, int idle, int interval, int timeout) -{ - int on = 1; -#ifdef TCP_KEEPCNT - if (timeout && interval) { - int count = (timeout + interval - 1) / interval; - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(on)) < 0) { - int xerrno = errno; - debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno)); - } - } -#endif -#ifdef TCP_KEEPIDLE - if (idle) { - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(on)) < 0) { - int xerrno = errno; - debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno)); - } - } -#endif -#ifdef TCP_KEEPINTVL - if (interval) { - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(on)) < 0) { - int xerrno = errno; - debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno)); - } - } -#endif - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0) { - int xerrno = errno; - debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno)); - } -} - void comm_init(void) { diff --git a/src/comm.h b/src/comm.h index 2e9dea96fa..c27fe01045 100644 --- a/src/comm.h +++ b/src/comm.h @@ -23,7 +23,6 @@ bool comm_iocallbackpending(void); /* inline candidate */ int commSetNonBlocking(int fd); int commUnsetNonBlocking(int fd); void commSetCloseOnExec(int fd); -void commSetTcpKeepalive(int fd, int idle, int interval, int timeout); void _comm_close(int fd, char const *file, int line); #define comm_close(x) (_comm_close((x), __FILE__, __LINE__)) void old_comm_reset_close(int fd); diff --git a/src/comm/Makefile.am b/src/comm/Makefile.am index 0c5d24e904..a5c933d608 100644 --- a/src/comm/Makefile.am +++ b/src/comm/Makefile.am @@ -30,6 +30,8 @@ libcomm_la_SOURCES = \ ModSelectWin32.cc \ Read.cc \ Read.h \ + Tcp.cc \ + Tcp.h \ TcpAcceptor.cc \ TcpAcceptor.h \ UdpOpenDialer.h \ diff --git a/src/comm/Tcp.cc b/src/comm/Tcp.cc new file mode 100644 index 0000000000..59769a3233 --- /dev/null +++ b/src/comm/Tcp.cc @@ -0,0 +1,71 @@ +/* + * Copyright (C) 1996-2021 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +/* DEBUG: section 05 TCP Socket Functions */ + +#include "squid.h" +#include "comm/Tcp.h" +#include "Debug.h" + +#if HAVE_NETINET_TCP_H +#include +#endif +#include + +/// setsockopt(2) wrapper +template +static bool +SetSocketOption(const int fd, const int level, const int optName, const Option &optValue) +{ +#if HAVE_STD_IS_TRIVIALLY_COPYABLE + static_assert(std::is_trivially_copyable