]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Make some alsa operation sequences un-cancellable. Make some cleanup sequences un...
authorMike Brady <mikebrady@eircom.net>
Sat, 24 Nov 2018 22:28:52 +0000 (22:28 +0000)
committerMike Brady <mikebrady@eircom.net>
Sat, 24 Nov 2018 22:28:52 +0000 (22:28 +0000)
audio_alsa.c
rtp.c

index 5ca4836ca20ffbc8f34e63de337c79d9530c5329..24132fe681077afee2ae1e1e090dc03c5f9124a9 100644 (file)
@@ -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 0c97fc31a25541f100006d50be35930c97ff69fa..afee1a4b6bfb8f5478e84e83da3c9d52e3b79f8b 100644 (file)
--- 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) {