Move cleanup push to start of RTSP initialisation. Take more care at startup and closedown to make stuff uncancellable.

This commit is contained in:
Mike Brady
2018-11-29 17:14:40 +00:00
parent 4a5b0009a4
commit f2a3ba00cc
+34 -14
View File
@@ -1591,7 +1591,7 @@ static void handle_set_parameter(rtsp_conn_info *conn, rtsp_message *req, rtsp_m
}
static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
debug(2, "Connection %d: ANNOUNCE", conn->connection_number);
debug(3, "Connection %d: ANNOUNCE", conn->connection_number);
int have_the_player = 0;
int should_wait = 0; // this will be true if you're trying to break in to the current session
@@ -1608,8 +1608,8 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
have_the_player = 1;
warn("Duplicate ANNOUNCE, by the look of it!");
} else if (playing_conn->stop) {
debug(1, "Connection %d: ANNOUNCE: already shutting down; waiting for it...",
playing_conn->connection_number);
debug(1, "Connection %d ANNOUNCE is waiting for connection %d to shut down.",
conn->connection_number, playing_conn->connection_number);
should_wait = 1;
} else if (config.allow_session_interruption == 1) {
debug(2, "Connection %d: ANNOUNCE: asking playing connection %d to shut down.",
@@ -2062,10 +2062,14 @@ authenticate:
void rtsp_conversation_thread_cleanup_function(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
// debug(1, "Connection %d: rtsp_conversation_thread_func_cleanup_function called.",
// conn->connection_number);
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState);
debug(3, "Connection %d: rtsp_conversation_thread_func_cleanup_function called.",
conn->connection_number);
if (conn->player_thread)
player_stop(conn);
if (conn->fd > 0) {
debug(3, "Connection %d: closing fd %d.", conn->connection_number, conn->fd);
close(conn->fd);
@@ -2096,11 +2100,8 @@ void rtsp_conversation_thread_cleanup_function(void *arg) {
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);
@@ -2114,6 +2115,7 @@ void rtsp_conversation_thread_cleanup_function(void *arg) {
debug(2, "Connection %d: RTSP thread terminated.", conn->connection_number);
conn->running = 0;
pthread_setcancelstate(oldState, NULL);
}
void msg_cleanup_function(void *arg) {
@@ -2148,6 +2150,9 @@ static void *rtsp_conversation_thread_func(void *pconn) {
die("Connection %d: error %d initialising flow control condition variable.",
conn->connection_number, rc);
// nothing before this is cancellable
pthread_cleanup_push(rtsp_conversation_thread_cleanup_function, (void *)conn);
rtp_initialise(conn);
char *hdr = NULL;
@@ -2156,7 +2161,6 @@ static void *rtsp_conversation_thread_func(void *pconn) {
int rtsp_read_request_attempt_count = 1; // 1 means exit immediately
rtsp_message *req, *resp;
pthread_cleanup_push(rtsp_conversation_thread_cleanup_function, (void *)conn);
while (conn->stop == 0) {
int debug_level = 3; // for printing the request and response
reply = rtsp_read_request(conn, &req);
@@ -2232,6 +2236,12 @@ static void *rtsp_conversation_thread_func(void *pconn) {
debug(1, "Connection %d: Unable to write an RTSP message response. Terminating the "
"connection.",
conn->connection_number);
struct linger so_linger;
so_linger.l_onoff = 1; // "true"
so_linger.l_linger = 0;
err = setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger);
if (err)
debug(1, "Could not set the RTSP socket to abort due to a write error on closing.");
conn->stop = 1;
// if (debuglev >= 1)
// debuglev = 3; // see what happens next
@@ -2249,7 +2259,14 @@ static void *rtsp_conversation_thread_func(void *pconn) {
rtsp_read_request_attempt_count--;
if (rtsp_read_request_attempt_count == 0) {
tstop = 1;
// if ((reply == rtsp_read_request_response_read_error) && (debuglev != 0))
if (reply == rtsp_read_request_response_read_error) {
struct linger so_linger;
so_linger.l_onoff = 1; // "true"
so_linger.l_linger = 0;
int err = setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger);
if (err)
debug(1, "Could not set the RTSP socket to abort due to a read error on closing.");
}
// debuglev = 3; // see what happens next
} else {
if (reply == rtsp_read_request_response_channel_closed)
@@ -2298,15 +2315,20 @@ static const char *format_address(struct sockaddr *fsa) {
*/
void rtsp_listen_loop_cleanup_handler(__attribute__((unused)) void *arg) {
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState);
debug(1, "rtsp_listen_loop_cleanup_handler called.");
cancel_all_RTSP_threads();
int *sockfd = (int *)arg;
mdns_unregister();
if (sockfd)
free(sockfd);
pthread_setcancelstate(oldState, NULL);
}
void rtsp_listen_loop(void) {
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState);
struct addrinfo hints, *info, *p;
char portstr[6];
int *sockfd = NULL;
@@ -2405,9 +2427,7 @@ void rtsp_listen_loop(void) {
mdns_register();
// printf("Listening for connections.");
// shairport_startup_complete();
pthread_setcancelstate(oldState, NULL);
int acceptfd;
struct timeval tv;
pthread_cleanup_push(rtsp_listen_loop_cleanup_handler, (void *)sockfd);
@@ -2509,6 +2529,6 @@ void rtsp_listen_loop(void) {
}
} while (1);
pthread_cleanup_pop(0);
pthread_cleanup_pop(1); // should never happen
debug(1, "Oops -- fell out of the RTSP select loop");
}