From: Mike Brady Date: Wed, 28 Nov 2018 17:18:03 +0000 (+0000) Subject: Move watchdog to cover connection from start, not just from start of play. Start... X-Git-Tag: 3.3RC0~135 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22f3e3e318d91d6e888f700bb2661dc3e32326cb;p=thirdparty%2Fshairport-sync.git Move watchdog to cover connection from start, not just from start of play. Start investigating UDP port allocation. Tidy up handling or RTSP write errors -- remove the pselect code from before a write. --- diff --git a/audio_alsa.c b/audio_alsa.c index dc6f11d8..00c33900 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -980,7 +980,7 @@ static int play(void *buf, int samples) { if (samples == 0) debug(1, "empty buffer being passed to pcm_writei -- skipping it"); if ((samples != 0) && (buf != NULL)) { - debug(3,"write %d frames.",samples); + debug(3, "write %d frames.", samples); err = alsa_pcm_write(alsa_handle, buf, samples); if (err < 0) { frame_index = 0; @@ -1066,7 +1066,7 @@ static void flush(void) { if ((derr = snd_pcm_hw_free(alsa_handle))) debug(1, "Error %d (\"%s\") freeing the output device hardware.", derr, snd_strerror(derr)); - + // flush also closes the device if ((derr = snd_pcm_close(alsa_handle))) debug(1, "Error %d (\"%s\") closing the output device.", derr, snd_strerror(derr)); diff --git a/common.c b/common.c index 0d76a4f4..76cf8204 100644 --- a/common.c +++ b/common.c @@ -96,7 +96,10 @@ sigset_t pselect_sigset; static uint16_t UDPPortIndex = 0; -void resetFreeUDPPort() { UDPPortIndex = 0; } +void resetFreeUDPPort() { + debug(1,"Resetting UDP Port Suggestion to %u",config.udp_port_base); + UDPPortIndex = 0; +} uint16_t nextFreeUDPPort() { if (UDPPortIndex == 0) diff --git a/player.c b/player.c index 3507db6b..4e2bfc4f 100644 --- a/player.c +++ b/player.c @@ -114,7 +114,6 @@ uint64_t modulo_64_offset(uint64_t from, uint64_t to) { } void do_flush(uint32_t timestamp, rtsp_conn_info *conn); -void *player_watchdog_thread_code(void *arg); static void ab_resync(rtsp_conn_info *conn) { int i; @@ -1431,12 +1430,6 @@ void player_thread_cleanup_handler(void *arg) { #endif debug(2, "Cancelling timing, control and audio threads..."); - debug(2, "Cancel watchdog thread."); - pthread_cancel(conn->player_watchdog_thread); - debug(2, "Join watchdog thread."); - pthread_join(conn->player_watchdog_thread, NULL); - debug(2, "Delete watchdog mutex."); - pthread_mutex_destroy(&conn->watchdog_mutex); debug(2, "Cancel timing thread."); pthread_cancel(conn->rtp_timing_thread); debug(2, "Join timing thread."); @@ -1730,10 +1723,6 @@ void *player_thread_func(void *arg) { pthread_create(&conn->rtp_control_thread, NULL, &rtp_control_receiver, (void *)conn); pthread_create(&conn->rtp_timing_thread, NULL, &rtp_timing_receiver, (void *)conn); - // create the watchdog mutex and start the watchdog thread; - pthread_mutex_init(&conn->watchdog_mutex, NULL); - pthread_create(&conn->player_watchdog_thread, NULL, &player_watchdog_thread_code, (void *)conn); - pthread_cleanup_push(player_thread_cleanup_handler, arg); // undo what's been done so far // stop looking elsewhere for DACP stuff @@ -2799,38 +2788,4 @@ int player_stop(rtsp_conn_info *conn) { // debuglev = dl; return -1; } -} - -void player_watchdog_thread_cleanup_handler(void *arg) { - rtsp_conn_info *conn = (rtsp_conn_info *)arg; - debug(2, "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 player thread is doing something...", - conn->connection_number); - if ((config.dont_check_timeout == 0) && (config.timeout != 0)) { - 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_fp() - last_watchdog_bark_time) >> 32; - uint64_t ct = config.timeout; // go from int to 64-bit int - - if (time_since_last_bark >= ct) { - 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); - } - } - } - } while (1); - pthread_cleanup_pop(0); // should never happen - pthread_exit(NULL); -} +} \ No newline at end of file diff --git a/rtp.c b/rtp.c index dba32390..1f908b0e 100644 --- a/rtp.c +++ b/rtp.c @@ -890,9 +890,14 @@ static uint16_t bind_port(int ip_family, const char *self_ip_address, uint32_t s if (ret < 0) { close(local_socket); - die("error: could not bind a UDP port! Check the udp_port_range is large enough -- it must be " + char errorstring[1024]; + strerror_r(errno, (char *)errorstring, sizeof(errorstring)); + die("error %d: \"%s\". Could not bind a UDP port! Check the udp_port_range is large enough -- " + "it must be " "at least 3, and 10 or more is suggested -- or " - "check for restrictive firewall settings or a bad router!"); + "check for restrictive firewall settings or a bad router! UDP base is %u, range is %u and " + "current suggestion is %u.", + errno, errorstring, config.udp_port_base, config.udp_port_range, desired_port); } uint16_t sport; diff --git a/rtsp.c b/rtsp.c index 478f20e6..beaaf8f7 100644 --- a/rtsp.c +++ b/rtsp.c @@ -253,6 +253,39 @@ int pc_queue_get_item(pc_queue *the_queue, void *the_stuff) { #endif +void player_watchdog_thread_cleanup_handler(void *arg) { + rtsp_conn_info *conn = (rtsp_conn_info *)arg; + debug(2, "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); + if ((config.dont_check_timeout == 0) && (config.timeout != 0)) { + 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_fp() - last_watchdog_bark_time) >> 32; + uint64_t ct = config.timeout; // go from int to 64-bit int + + if (time_since_last_bark >= ct) { + 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); + } + } + } + } while (1); + pthread_cleanup_pop(0); // should never happen + pthread_exit(NULL); +} + void ask_other_rtsp_conversation_threads_to_stop(pthread_t except_this_thread); void rtsp_request_shutdown_stream(void) { @@ -425,9 +458,9 @@ static void debug_print_msg_content(int level, rtsp_message *msg) { void msg_free(rtsp_message *msg) { if (msg) { - debug_mutex_lock(&reference_counter_lock,1000,3); + debug_mutex_lock(&reference_counter_lock, 1000, 3); msg->referenceCount--; - debug_mutex_unlock(&reference_counter_lock,3); + debug_mutex_unlock(&reference_counter_lock, 3); if (msg->referenceCount == 0) { unsigned int i; for (i = 0; i < msg->nheaders; i++) { @@ -695,10 +728,9 @@ int msg_write_response(int fd, rtsp_message *resp) { ssize_t reply = write(fd, pkt, p - pkt); if (reply == -1) { char errorstring[1024]; - strerror_r(errno, (char *)errorstring, sizeof(errorstring)); - debug(1, "msg_write_response error %d: \"%s\".", - errno, (char *)errorstring); - return -4; + strerror_r(errno, (char *)errorstring, sizeof(errorstring)); + debug(1, "msg_write_response error %d: \"%s\".", errno, (char *)errorstring); + return -4; } if (reply != p - pkt) { debug(1, "msg_write_response error -- requested bytes not fully written."); @@ -890,12 +922,14 @@ void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) { "timing_port=%d;server_" "port=%d", conn->local_control_port, conn->local_timing_port, conn->local_audio_port); + msg_add_header(resp, "Transport", resphdr); msg_add_header(resp, "Session", "1"); resp->respcode = 200; + debug(1, "Connection %d: SETUP with UDP ports Control: %d, Timing: %d and Audio: %d.", conn->connection_number, conn->local_control_port, conn->local_timing_port, conn->local_audio_port); return; error: @@ -2002,9 +2036,9 @@ void rtsp_conversation_thread_cleanup_function(void *arg) { if (conn->player_thread) player_stop(conn); if (conn->fd > 0) { - debug(3, "Connection %d: closing fd %d.", conn->connection_number,conn->fd); + debug(3, "Connection %d: closing fd %d.", conn->connection_number, conn->fd); close(conn->fd); - debug(3, "Connection %d: closed fd %d.", conn->connection_number,conn->fd); + debug(3, "Connection %d: closed fd %d.", conn->connection_number, conn->fd); } if (conn->auth_nonce) { free(conn->auth_nonce); @@ -2035,7 +2069,17 @@ void rtsp_conversation_thread_cleanup_function(void *arg) { debug(3, "Connection %d: Unlocking play lock.", conn->connection_number); playing_conn = NULL; } + debug_mutex_unlock(&playing_conn_lock, 3); + debug(2, "Cancel watchdog thread."); + pthread_cancel(conn->player_watchdog_thread); + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); + debug(2, "Join watchdog thread."); + pthread_join(conn->player_watchdog_thread, NULL); + pthread_setcancelstate(oldState, NULL); + debug(2, "Delete watchdog mutex."); + pthread_mutex_destroy(&conn->watchdog_mutex); debug(2, "Connection %d: RTSP thread terminated.", conn->connection_number); conn->running = 0; @@ -2049,6 +2093,10 @@ void msg_cleanup_function(void *arg) { static void *rtsp_conversation_thread_func(void *pconn) { rtsp_conn_info *conn = pconn; + // create the watchdog mutex and start the watchdog thread; + 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); @@ -2136,7 +2184,7 @@ static void *rtsp_conversation_thread_func(void *pconn) { } debug(debug_level, "Connection %d: RTSP Response:", conn->connection_number); debug_print_msg_headers(debug_level, resp); - + /* fd_set writefds; FD_ZERO(&writefds); @@ -2146,7 +2194,7 @@ static void *rtsp_conversation_thread_func(void *pconn) { } while (conn->stop == 0 && pselect(conn->fd + 1, NULL, &writefds, NULL, NULL, &pselect_sigset) <= 0); */ - + if (conn->stop == 0) { int err = msg_write_response(conn->fd, resp); if (err) { @@ -2154,8 +2202,8 @@ static void *rtsp_conversation_thread_func(void *pconn) { "connection.", conn->connection_number); conn->stop = 1; - if (debuglev >= 1) - debuglev = 3; // see what happens next + // if (debuglev >= 1) + // debuglev = 3; // see what happens next } } pthread_cleanup_pop(1); diff --git a/shairport.c b/shairport.c index c9212544..506f9feb 100644 --- a/shairport.c +++ b/shairport.c @@ -31,11 +31,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include