From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 29 Jun 2024 19:04:29 +0000 (+0100) Subject: Remove watchdog stuff. USe the session timeout to set the TCP keep intervals and... X-Git-Tag: 4.3.4~1^2~9 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=419ff394f5ace0f28752b1fc3219aafe098c6aab;p=thirdparty%2Fshairport-sync.git Remove watchdog stuff. USe the session timeout to set the TCP keep intervals and stuff. Change response to ETIMEDOUT to rtsp_read_request_response_immediate_shutdown_requested. --- diff --git a/rtsp.c b/rtsp.c index f997824e..1712e480 100644 --- a/rtsp.c +++ b/rtsp.c @@ -3,7 +3,7 @@ * Copyright (c) James Laird 2013 * Modifications associated with audio synchronization, multithreading and - * metadata handling copyright (c) Mike Brady 2014-2023 + * metadata handling copyright (c) Mike Brady 2014-2024 * All rights reserved. * * Permission is hereby granted, free of charge, to any person @@ -612,57 +612,6 @@ int get_play_lock(rtsp_conn_info *conn, int allow_session_interruption) { return response; } -void player_watchdog_thread_cleanup_handler(void *arg) { - rtsp_conn_info *conn = (rtsp_conn_info *)arg; - debug(3, "Connection %d: Watchdog Exit.", conn->connection_number); -} - -void *player_watchdog_thread_code(void *arg) { - pthread_cleanup_push(player_watchdog_thread_cleanup_handler, arg); - rtsp_conn_info *conn = (rtsp_conn_info *)arg; - do { - usleep(2000000); // check every two seconds - // debug(3, "Connection %d: Check the thread is doing something...", conn->connection_number); -#ifdef CONFIG_AIRPLAY_2 - if ((config.dont_check_timeout == 0) && (config.timeout != 0) && (conn->airplay_type == ap_1)) { -#else - if ((config.dont_check_timeout == 0) && (config.timeout != 0)) { -#endif - debug_mutex_lock(&conn->watchdog_mutex, 1000, 0); - uint64_t last_watchdog_bark_time = conn->watchdog_bark_time; - debug_mutex_unlock(&conn->watchdog_mutex, 0); - if (last_watchdog_bark_time != 0) { - uint64_t time_since_last_bark = - (get_absolute_time_in_ns() - last_watchdog_bark_time) / 1000000000; - uint64_t ct = config.timeout; // go from int to 64-bit int - - if (time_since_last_bark >= ct) { - conn->watchdog_barks++; - if (conn->watchdog_barks == 1) { - // debuglev = 3; // tell us everything. - debug(1, - "Connection %d: As Yeats almost said, \"Too long a silence / can make a stone " - "of the heart\".", - conn->connection_number); - conn->stop = 1; - pthread_cancel(conn->thread); - } else if (conn->watchdog_barks == 3) { - if ((config.cmd_unfixable) && (config.unfixable_error_reported == 0)) { - config.unfixable_error_reported = 1; - command_execute(config.cmd_unfixable, "unable_to_cancel_play_session", 1); - } else { - die("an unrecoverable error, \"unable_to_cancel_play_session\", has been detected.", - conn->connection_number); - } - } - } - } - } - } while (1); - pthread_cleanup_pop(0); // should never happen - pthread_exit(NULL); -} - static void track_thread(rtsp_conn_info *conn) { debug_mutex_lock(&conns_lock, 1000000, 3); // look for an empty slot first @@ -1349,8 +1298,11 @@ enum rtsp_read_request_response rtsp_read_request(rtsp_conn_info *conn, rtsp_mes continue; } if (errno == ETIMEDOUT) { - debug(1, "Connection %d: ETIMEDOUT -- keepalive timeout.", conn->connection_number); - reply = rtsp_read_request_response_channel_closed; + debug(1, + "Connection %d: As Yeats almost said, \"Too long a silence / can make a stone " + "of the heart\".", + conn->connection_number); + reply = rtsp_read_request_response_immediate_shutdown_requested; // Note: the socket will be closed when the thread exits goto shutdown; } @@ -2116,7 +2068,7 @@ struct pairings { uint8_t public_key[32]; struct pairings *next; -} * pairings; +} *pairings; static struct pairings *pairing_find(const char *device_id) { for (struct pairings *pairing = pairings; pairing; pairing = pairing->next) { @@ -5113,7 +5065,7 @@ void rtsp_conversation_thread_cleanup_function(void *arg) { if (conn != NULL) { int oldState; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); - debug(2, "Connection %d: %s rtsp_conversation_thread_func_cleanup_function called.", + debug(3, "Connection %d: %s rtsp_conversation_thread_func_cleanup_function called.", conn->connection_number, get_category_string(conn->airplay_stream_category)); #ifdef CONFIG_AIRPLAY_2 // AP2 @@ -5205,14 +5157,7 @@ void rtsp_conversation_thread_cleanup_function(void *arg) { if (rc) debug(1, "Connection %d: error %d destroying flush_mutex.", conn->connection_number, rc); - debug(3, "Cancel watchdog thread."); - pthread_cancel(conn->player_watchdog_thread); - debug(3, "Join watchdog thread."); - pthread_join(conn->player_watchdog_thread, NULL); - debug(3, "Delete watchdog mutex."); - pthread_mutex_destroy(&conn->watchdog_mutex); - - debug(2, "Connection %d: Closed.", conn->connection_number); + debug(3, "Connection %d: Closed.", conn->connection_number); conn->running = 0; // for the garbage collector pthread_setcancelstate(oldState, NULL); } @@ -5226,11 +5171,6 @@ void msg_cleanup_function(void *arg) { static void *rtsp_conversation_thread_func(void *pconn) { rtsp_conn_info *conn = pconn; - // create the watchdog mutex, initialise the watchdog time and start the watchdog thread; - conn->watchdog_bark_time = get_absolute_time_in_ns(); - pthread_mutex_init(&conn->watchdog_mutex, NULL); - pthread_create(&conn->player_watchdog_thread, NULL, &player_watchdog_thread_code, (void *)conn); - int rc = pthread_mutex_init(&conn->flush_mutex, NULL); if (rc) die("Connection %d: error %d initialising flush_mutex.", conn->connection_number, rc); @@ -5649,22 +5589,26 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { size_of_reply = sizeof(SOCKADDR); if (getsockname(conn->fd, (struct sockaddr *)&conn->local, &size_of_reply) == 0) { + if ((config.dont_check_timeout == 0) && (config.timeout != 0)) { // skip this stuff in OpenBSD #ifndef COMPILE_FOR_OPENBSD - // Thanks to https://holmeshe.me/network-essentials-setsockopt-SO_KEEPALIVE/ for this. + // Thanks to https://holmeshe.me/network-essentials-setsockopt-SO_KEEPALIVE/ for this. - // turn on keepalive stuff -- wait for keepidle + (keepcnt * keepinttvl time) seconds - // before giving up an ETIMEOUT error is returned if the keepalive check fails + // turn on keepalive stuff -- wait for keepidle + (keepcnt * keepinttvl time) seconds + // before giving up an ETIMEOUT error is returned if the keepalive check fails - // if TCP_KEEPINTVL is defined, check a few times before declaring the line dead - // otherwise just wait a little while longer + // if TCP_KEEPINTVL is defined, check a few times before declaring the line dead + // otherwise just wait a little while longer #ifdef TCP_KEEPINTVL - int keepAliveIdleTime = 35; // wait this many seconds before checking for a dropped client - int keepAliveCount = 5; // check this many times - int keepAliveInterval = 5; // wait this many seconds between checks + int keepAliveIdleTime = + config.timeout - + 5 * 5; // wait this many seconds before checking for a dropped client + int keepAliveCount = 5; // check this many times + int keepAliveInterval = 5; // wait this many seconds between checks #else - int keepAliveIdleTime = 60; // wait this many seconds before dropping a client + int keepAliveIdleTime = + config.timeout; // wait this many seconds before dropping a client #endif // --- the following is a bit too complicated @@ -5681,24 +5625,24 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { #define KEEP_ALIVE_OR_IDLE_OPTION TCP_KEEPIDLE #endif - if (setsockopt(conn->fd, SOL_OPTION, KEEP_ALIVE_OR_IDLE_OPTION, - (void *)&keepAliveIdleTime, sizeof(keepAliveIdleTime))) { - debug(1, "can't set the keepAliveIdleTime wait time"); - } + if (setsockopt(conn->fd, SOL_OPTION, KEEP_ALIVE_OR_IDLE_OPTION, + (void *)&keepAliveIdleTime, sizeof(keepAliveIdleTime))) { + debug(1, "can't set the keepAliveIdleTime wait time"); + } // --- // if TCP_KEEPINTVL is defined... #ifdef TCP_KEEPINTVL - if (setsockopt(conn->fd, SOL_OPTION, TCP_KEEPCNT, (void *)&keepAliveCount, - sizeof(keepAliveCount))) { - debug(1, "can't set the keepAliveCount count"); - } - if (setsockopt(conn->fd, SOL_OPTION, TCP_KEEPINTVL, (void *)&keepAliveInterval, - sizeof(keepAliveInterval))) { - debug(1, "can't set the keepAliveCount count interval"); - }; + if (setsockopt(conn->fd, SOL_OPTION, TCP_KEEPCNT, (void *)&keepAliveCount, + sizeof(keepAliveCount))) { + debug(1, "can't set the keepAliveCount count"); + } + if (setsockopt(conn->fd, SOL_OPTION, TCP_KEEPINTVL, (void *)&keepAliveInterval, + sizeof(keepAliveInterval))) { + debug(1, "can't set the keepAliveCount count interval"); + }; #endif #endif - + } // initialise the connection info void *client_addr = NULL, *self_addr = NULL; conn->connection_ip_family = conn->local.SAFAMILY;