From: Mike Brady Date: Sat, 24 Nov 2018 22:28:52 +0000 (+0000) Subject: Make some alsa operation sequences un-cancellable. Make some cleanup sequences un... X-Git-Tag: 3.3RC0~119^2~9^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3b4654df7703c58d3d2fefa74c7543ed39851875;p=thirdparty%2Fshairport-sync.git Make some alsa operation sequences un-cancellable. Make some cleanup sequences un-cancellable. --- diff --git a/audio_alsa.c b/audio_alsa.c index 5ca4836c..24132fe6 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -405,6 +405,8 @@ static int init(int argc, char **argv) { debug(1, "alsa output device name is \"%s\".", alsa_out_dev); if (hardware_mixer) { + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable if (alsa_mix_dev == NULL) alsa_mix_dev = alsa_out_dev; @@ -491,6 +493,7 @@ static int init(int argc, char **argv) { } debug_mutex_unlock(&alsa_mutex, 3); // release the mutex pthread_cleanup_pop(0); + pthread_setcancelstate(oldState, NULL); } else { // debug(1, "Has no mixer and thus no hardware mute."); } @@ -504,7 +507,7 @@ static void deinit(void) { stop(); } -int open_alsa_device(void) { +int actual_open_alsa_device(void) { // the alsa mutex is already acquired when this is called const snd_pcm_uframes_t minimal_buffer_headroom = 352 * 2; // we accept this much headroom in the hardware buffer, but we'll @@ -851,6 +854,15 @@ int open_alsa_device(void) { return 0; } +int open_alsa_device(void) { + int result; + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable + result = actual_open_alsa_device(); + pthread_setcancelstate(oldState, NULL); + return result; +} + static void start(int i_sample_rate, int i_sample_format) { // debug(2,"audio_alsa start called."); if (i_sample_rate == 0) @@ -874,6 +886,8 @@ int delay(long *the_delay) { if (alsa_handle == NULL) { return -ENODEV; } else { + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 1); int derr; snd_pcm_state_t dac_state = snd_pcm_state(alsa_handle); @@ -926,6 +940,7 @@ int delay(long *the_delay) { // here, occasionally pretend there's a problem with pcm_get_delay() // if ((random() % 100000) < 3) // keep it pretty rare // reply = -EIO; // pretend something bad has happened + pthread_setcancelstate(oldState, NULL); return reply; } } @@ -945,10 +960,13 @@ int get_rate_information(uint64_t *elapsed_time, uint64_t *frames_played) { static int play(void *buf, int samples) { // debug(3,"audio_alsa play called."); + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable int ret = 0; if (alsa_handle == NULL) { + pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 1); - ret = open_alsa_device(); + ret = actual_open_alsa_device(); if (ret == 0) { if (audio_alsa.volume) do_volume(set_volume); @@ -1047,13 +1065,14 @@ static int play(void *buf, int samples) { debug_mutex_unlock(&alsa_mutex, 3); pthread_cleanup_pop(0); // release the mutex } + pthread_setcancelstate(oldState, NULL); return ret; } static void flush(void) { // debug(2,"audio_alsa flush called."); int oldState; - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 1); int derr; do_mute(1); @@ -1094,6 +1113,8 @@ static void parameters(audio_parameters *info) { } void do_volume(double vol) { // caller is assumed to have the alsa_mutex when using this function + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable debug(3, "Setting volume db to %f.", vol); set_volume = vol; if (volume_set_request && (open_mixer() == 1)) { @@ -1125,6 +1146,7 @@ void do_volume(double vol) { // caller is assumed to have the alsa_mutex when us volume_set_request = 0; // any external request that has been made is now satisfied close_mixer(); } + pthread_setcancelstate(oldState, NULL); } void volume(double vol) { @@ -1165,6 +1187,9 @@ static void mute(int mute_state_requested) { void do_mute(int mute_state_requested) { + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable + // if a mute is requested now, then // if an external mute request is in place, leave everything muted // otherwise, if an external mute request is pending, action it @@ -1205,4 +1230,6 @@ void do_mute(int mute_state_requested) { } } mute_request_pending = 0; + + pthread_setcancelstate(oldState, NULL); } diff --git a/rtp.c b/rtp.c index 0c97fc31..afee1a4b 100644 --- a/rtp.c +++ b/rtp.c @@ -98,14 +98,16 @@ uint64_t local_to_remote_time_difference_now(rtsp_conn_info *conn) { } void rtp_audio_receiver_cleanup_handler(void *arg) { + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); debug(3, "Audio Receiver Cleanup."); rtsp_conn_info *conn = (rtsp_conn_info *)arg; debug(3, "shutdown audio socket."); shutdown(conn->audio_socket, SHUT_RDWR); debug(3, "close audio socket."); close(conn->audio_socket); - - debug(3, "Audio Receiver Cleanup Successful."); + debug(3, "Connection %d: Audio Receiver Cleanup.", conn->connection_number); + pthread_setcancelstate(oldState, NULL); } void *rtp_audio_receiver(void *arg) { @@ -240,13 +242,16 @@ void *rtp_audio_receiver(void *arg) { } void rtp_control_handler_cleanup_handler(void *arg) { + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); debug(3, "Control Receiver Cleanup."); rtsp_conn_info *conn = (rtsp_conn_info *)arg; debug(3, "shutdown control socket."); shutdown(conn->control_socket, SHUT_RDWR); debug(3, "close control socket."); close(conn->control_socket); - debug(3, "Control Receiver Cleanup Successful."); + debug(3, "Connection %d: Control Receiver Cleanup.", conn->connection_number); + pthread_setcancelstate(oldState, NULL); } void *rtp_control_receiver(void *arg) { @@ -495,7 +500,13 @@ void *rtp_control_receiver(void *arg) { pthread_exit(NULL); } +void rtp_timing_sender_cleanup_handler(void *arg) { + rtsp_conn_info *conn = (rtsp_conn_info *)arg; + debug(3, "Connection %d: Timing Sender Cleanup.", conn->connection_number); +} + void *rtp_timing_sender(void *arg) { + pthread_cleanup_push(rtp_timing_sender_cleanup_handler, arg); rtsp_conn_info *conn = (rtsp_conn_info *)arg; struct timing_request { char leader; @@ -555,10 +566,13 @@ void *rtp_timing_sender(void *arg) { usleep(3000000); } debug(3, "rtp_timing_sender thread interrupted. This should never happen."); + pthread_cleanup_pop(0); // don't execute anything here. pthread_exit(NULL); } void rtp_timing_receiver_cleanup_handler(void *arg) { + int oldState; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); debug(3, "Timing Receiver Cleanup."); rtsp_conn_info *conn = (rtsp_conn_info *)arg; pthread_cancel(conn->timer_requester); @@ -567,7 +581,8 @@ void rtp_timing_receiver_cleanup_handler(void *arg) { shutdown(conn->timing_socket, SHUT_RDWR); debug(3, "close timing socket."); close(conn->timing_socket); - debug(3, "Timing Receiver Cleanup Successful."); + debug(3, "Connection %d: Timing Receiver Cleanup.", conn->connection_number); + pthread_setcancelstate(oldState, NULL); } void *rtp_timing_receiver(void *arg) {