From 9e9f2b81652d2ed551e9f890d27cf5a0da6ba5f6 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Tue, 30 Apr 2019 17:04:59 -0500 Subject: [PATCH] Detect timeout conditions more aggressively on Linux This mitigates a fairly rare problem we see with our kiosk mode clients. That is, normally if something goes wrong with a client connection (e.g. the session is killed, or the server is restarted ), the kiosk will exit on disconnect, and we get a chance to retry the connection, or present the user with a 'server down' style message. But in the case of a serious network problem or a server hard power cycle (i.e. no TCP FIN packets can flow), our end user behavior is not ideal - the kiosk appears to hang solid, requiring a power cycle. That's because we've got the stock keepalive timeouts, or about 2 hours and 11 minutes, before the client sees the disconnect. This change will cause the client to recognize the server has vanished without a TCP FIN after 75 seconds. See this thread: https://lists.freedesktop.org/archives/spice-devel/2017-March/036553.html As well as this bug: https://bugzilla.redhat.com/show_bug.cgi?id=1436589 Signed-off-by: Jeremy White (cherry picked from commit 677782fb6aa471d5e6d007744a5c6564b1f3021f) --- src/spice-session.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/spice-session.c b/src/spice-session.c index ee6e4cf..59c20c7 100644 --- a/src/spice-session.c +++ b/src/spice-session.c @@ -17,6 +17,8 @@ */ #include "config.h" +/* include first, on Windows will override winsock definitions */ +#include #include #include #ifdef G_OS_UNIX @@ -39,6 +41,13 @@ struct channel { RingItem link; }; +#if !defined(SOL_TCP) && defined(IPPROTO_TCP) +#define SOL_TCP IPPROTO_TCP +#endif +#if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE) && defined(__APPLE__) +#define TCP_KEEPIDLE TCP_KEEPALIVE +#endif + #define IMAGES_CACHE_SIZE_DEFAULT (1024 * 1024 * 80) #define MIN_GLZ_WINDOW_SIZE_DEFAULT (1024 * 1024 * 12) #define MAX_GLZ_WINDOW_SIZE_DEFAULT MIN((LZ_MAX_WINDOW_SIZE * 4), 1024 * 1024 * 64) @@ -2233,6 +2242,23 @@ GSocketConnection* spice_session_channel_open_host(SpiceSession *session, SpiceC g_socket_set_timeout(socket, 0); g_socket_set_blocking(socket, FALSE); g_socket_set_keepalive(socket, TRUE); + + /* Make client timeouts a bit more responsive */ +#if defined(_WIN32) + /* Windows does not support setting count */ + struct tcp_keepalive keepalive = { + TRUE, + 30 * 1000, + 5 * 1000 + }; + DWORD written; + WSAIoctl(g_socket_get_fd(socket), SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), + NULL, 0, &written, NULL, NULL); +#elif defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) + g_socket_set_option(socket, SOL_TCP, TCP_KEEPIDLE, 30, NULL); + g_socket_set_option(socket, SOL_TCP, TCP_KEEPINTVL, 15, NULL); + g_socket_set_option(socket, SOL_TCP, TCP_KEEPCNT, 3, NULL); +#endif } g_clear_object(&open_host.client); -- 2.21.0