summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 7a65aad)
raw | patch | inline | side by side (parent: 7a65aad)
author | Marc Fournier <marc.fournier@camptocamp.com> | |
Sat, 13 Feb 2016 10:51:23 +0000 (11:51 +0100) | ||
committer | Marc Fournier <marc.fournier@camptocamp.com> | |
Tue, 9 Aug 2016 09:05:37 +0000 (11:05 +0200) |
Enables the TCP keepalive mechanism on a given socket.
This would typically be used on sockets opened by write plugins
which submit data to a remote server.
Up to now, collectd fails to notice when a remote server dies without
properly closing the network connection, leading to more and more memory
getting allocated as the values pile up in the write queue.
The keepalive values are proportional to the configured `Interval`. The
first probe is emitted `10 x Interval` seconds after the last TCP packet
was seen, and then once per `Interval` until the threshold defined by
the OS is reached.
See: http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#checkdeadpeers
This would typically be used on sockets opened by write plugins
which submit data to a remote server.
Up to now, collectd fails to notice when a remote server dies without
properly closing the network connection, leading to more and more memory
getting allocated as the values pile up in the write queue.
The keepalive values are proportional to the configured `Interval`. The
first probe is emitted `10 x Interval` seconds after the last TCP packet
was seen, and then once per `Interval` until the threshold defined by
the OS is reached.
See: http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#checkdeadpeers
src/daemon/common.c | patch | blob | history | |
src/daemon/common.h | patch | blob | history |
diff --git a/src/daemon/common.c b/src/daemon/common.c
index b60530a18304d858c7334d8257b133b158467ef5..c4dbecbec9cb8c9c4d883d9b11def27ca1316390 100644 (file)
--- a/src/daemon/common.c
+++ b/src/daemon/common.c
# include <netinet/in.h>
#endif
+#if HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+
/* for ntohl and htonl */
#if HAVE_ARPA_INET_H
# include <arpa/inet.h>
return (-1);
} /* int service_name_to_port_number */
+void set_sock_opts (int sockfd) /* {{{ */
+{
+ int status;
+ int socktype;
+
+ socklen_t socklen = sizeof (socklen_t);
+ int so_keepalive = 1;
+ int tcp_keepidle = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 100 + 1);
+ int tcp_keepintvl = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 1000 + 1);
+
+ status = getsockopt (sockfd, SOL_SOCKET, SO_TYPE, &socktype, &socklen);
+ if (status != 0)
+ {
+ WARNING ("set_sock_opts: failed to determine socket type");
+ return;
+ }
+
+ if (socktype == SOCK_STREAM)
+ {
+ status = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
+ &so_keepalive, sizeof (so_keepalive));
+ if (status != 0)
+ WARNING ("set_sock_opts: failed to set socket keepalive flag");
+
+#ifdef TCP_KEEPIDLE
+ status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
+ &tcp_keepidle, sizeof (tcp_keepidle));
+ if (status != 0)
+ WARNING ("set_sock_opts: failed to set socket tcp keepalive time");
+#endif
+
+#ifdef TCP_KEEPINTVL
+ status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
+ &tcp_keepintvl, sizeof (tcp_keepintvl));
+ if (status != 0)
+ WARNING ("set_sock_opts: failed to set socket tcp keepalive interval");
+#endif
+ }
+} /* }}} void set_sock_opts */
+
int strtoderive (const char *string, derive_t *ret_value) /* {{{ */
{
derive_t tmp;
diff --git a/src/daemon/common.h b/src/daemon/common.h
index 8079661a9b56aef666fb8499f90ea22fd9ca7317..5ad2b50dc9d78778fb8b20f1577c3c6d33c48779 100644 (file)
--- a/src/daemon/common.h
+++ b/src/daemon/common.h
* (in the range [1-65535]). Returns less than zero on error. */
int service_name_to_port_number (const char *service_name);
+/* Sets various, non-default, socket options */
+void set_sock_opts (int sockfd);
+
/** Parse a string to a derive_t value. Returns zero on success or non-zero on
* failure. If failure is returned, ret_value is not touched. */
int strtoderive (const char *string, derive_t *ret_value);