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:
+2
-2
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user