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.

This commit is contained in:
Mike Brady
2018-11-28 17:18:03 +00:00
parent 4ab81ce0b7
commit 22f3e3e318
6 changed files with 75 additions and 64 deletions
+2 -2
View File
@@ -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));
+4 -1
View File
@@ -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)
+1 -46
View File
@@ -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);
}
}
+7 -2
View File
@@ -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;
+60 -12
View File
@@ -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);
+1 -1
View File
@@ -31,11 +31,11 @@
#include <libconfig.h>
#include <libgen.h>
#include <memory.h>
#include <net/if.h>
#include <popt.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>