]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Ensure no pthread cancellation can occur during an ALSA-related call.
authorMike Brady <mikebrady@eircom.net>
Mon, 3 Dec 2018 12:44:57 +0000 (12:44 +0000)
committerMike Brady <mikebrady@eircom.net>
Mon, 3 Dec 2018 12:44:57 +0000 (12:44 +0000)
1  2 
audio_alsa.c
rtp.c

diff --cc audio_alsa.c
index a5c47d8c752436e1dc78490a34d0bb1b0949358d,372f84d1bf204442524f59d02fb4136a4b2a76f0..98182989943dee8fbe22a2b7bcabd47b9f493562
@@@ -136,6 -134,6 +136,8 @@@ static void help(void) 
  
  void set_alsa_out_dev(char *dev) { alsa_out_dev = dev; }
  
++
++//assuming pthread cancellation is disabled
  int open_mixer() {
    int response = 0;
    if (hardware_mixer) {
    return response;
  }
  
++//assuming pthread cancellation is disabled
  void close_mixer() {
    if (alsa_mix_handle) {
      snd_mixer_close(alsa_mix_handle);
    }
  }
  
++//assuming pthread cancellation is disabled
  void do_snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *mix_elem, double vol) {
    if (snd_mixer_selem_set_playback_dB_all(mix_elem, vol, 0) != 0) {
      debug(1, "Can't set playback volume accurately to %f dB.", vol);
  }
  
  static int init(int argc, char **argv) {
++      // for debugging
 +  snd_output_stdio_attach(&output, stdout, 0);
 +
    // debug(2,"audio_alsa init called.");
    int response = 0; // this will be what we return to the caller.
    const char *str;
      warn("Invalid audio argument: \"%s\" -- ignored", argv[optind]);
    }
  
-   debug(1, "alsa output device name is \"%s\".", alsa_out_dev);
+   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;
      }
      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.");
+     debug(1, "alsa: no hardware mixer selected.");
    }
  
    alsa_mix_handle = NULL;
@@@ -511,7 -504,7 +516,8 @@@ static void deinit(void) 
    stop();
  }
  
 -int open_alsa_device(void) {
++//assuming pthread cancellation is disabled
 +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
@@@ -906,42 -867,6 +912,43 @@@ static void start(int i_sample_rate, in
    measurement_data_is_valid = 0;
  }
  
++//assuming pthread cancellation is disabled
 +int my_snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) {
 +  int ret;
 +  snd_pcm_status_t *alsa_snd_pcm_status;
 +  snd_pcm_status_alloca(&alsa_snd_pcm_status);
 +
 +  struct timespec tn;                // time now
 +  snd_htimestamp_t update_timestamp; // actually a struct timespec
 +
 +  ret = snd_pcm_status(pcm, alsa_snd_pcm_status);
 +  if (ret) {
 +    *delayp = 0;
 +    return ret;
 +  }
 +
 +  snd_pcm_state_t state = snd_pcm_status_get_state(alsa_snd_pcm_status);
 +  if (state != SND_PCM_STATE_RUNNING) {
 +    *delayp = 0;
 +    return -EIO; // might be a better code than this...
 +  }
 +
 +  clock_gettime(CLOCK_MONOTONIC, &tn);
 +  snd_pcm_status_get_htstamp(alsa_snd_pcm_status, &update_timestamp);
 +
 +  uint64_t t1 = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
 +  uint64_t t2 = update_timestamp.tv_sec * (uint64_t)1000000000 + update_timestamp.tv_nsec;
 +  uint64_t delta = t1 - t2;
 +
 +  uint64_t frames_played_since_last_interrupt =
 +      ((uint64_t)desired_sample_rate * delta) / 1000000000;
 +  snd_pcm_sframes_t frames_played_since_last_interrupt_sized = frames_played_since_last_interrupt;
 +
 +  *delayp =
 +      snd_pcm_status_get_delay(alsa_snd_pcm_status) - frames_played_since_last_interrupt_sized;
 +  return 0;
 +}
 +
  int delay(long *the_delay) {
    // snd_pcm_sframes_t is a signed long -- hence the return of a "long"
    int reply = 0;
@@@ -1125,10 -1045,9 +1133,10 @@@ static int play(void *buf, int samples
        frame_index = 0;
        measurement_data_is_valid = 0;
      }
-     debug_mutex_unlock(&alsa_mutex, 3);
+     debug_mutex_unlock(&alsa_mutex, 0);
      pthread_cleanup_pop(0); // release the mutex
    }
 +  pthread_setcancelstate(oldState, NULL);
    return ret;
  }
  
@@@ -1292,7 -1205,5 +1300,6 @@@ void do_mute(int mute_state_requested) 
        close_mixer();
      }
    }
--  mute_request_pending = 0;
-   
++  mute_request_pending = 0;  
 +  pthread_setcancelstate(oldState, NULL);
  }
diff --cc rtp.c
Simple merge