title: ALSA: cannot recovery from underrun, prepare failed: Broken pipe
body: <p>I'm writing a program that reads from two mono ALSA devices and writes them to one stereo ALSA device.</p>
  
  <p>I use three threads and ping-pong buffer to manage them. Two reading threads and one writing threads. Their configurations are as follows:</p>
  
  <pre><code>// Capture ALSA device 
  alsaBufferSize = 16384;
  alsaCaptureChunkSize = 4096;
  bitsPerSample = 16;
  samplingFrequency = 24000;
  numOfChannels = 1;
  block = true;
  accessType = SND_PCM_ACCESS_RW_INTERLEAVED;
  
  // Playback device (only list params that are different from above)
  alsaBufferSize = 16384 * 2;
  numOfChannels = 2;
  accessType = SND_PCM_ACCESS_RW_NON_INTERLEAVED;
  </code></pre>
  
  <p>Two reading threads would write ping buffer and then pong buffer. The writing thread would wait for any of two buffer ready, lock it, read from it, and then unlock it.</p>
  
  <p>But when I run this program, xrun appears and can't be recovered.</p>
  
  <pre><code>ALSA lib pcm.c:7316:(snd_pcm_recover) underrun occurred
  ALSA lib pcm.c:7319:(snd_pcm_recover) cannot recovery from underrun, prepare failed: Broken pipe
  </code></pre>
  
  <p>Below is my code for writing to ALSA playback device:</p>
  
  <pre><code>bool CALSAWriter::writen(uint8_t**  a_pOutputBuffer, uint32_t a_rFrames)
  {
  
      bool ret = false;
  
      // 1. write audio chunk from ALSA
      const snd_pcm_sframes_t alsaCaptureChunkSize = static_cast&lt;snd_pcm_sframes_t&gt;(a_rFrames); //(m_pALSACfg-&gt;alsaCaptureChunkSize);
  
      const snd_pcm_sframes_t writenFrames = snd_pcm_writen(m_pALSAHandle, (void**)a_pOutputBuffer, alsaCaptureChunkSize); 
  
      if (0 &lt; writenFrames)
      {// write succeeded
  
          ret = true;
  
      }
      else
      {// write failed
          logPrint("CALSAWriter WRITE FAILED for  writen farmes = %d ", writenFrames);
          ret = false;
          const int alsaReadError = static_cast&lt;int&gt;(writenFrames);// alsa error is of int type
  
          if (ALSA_OK == snd_pcm_recover(m_pALSAHandle, alsaReadError, 0))
          {// recovery succeeded
              a_rFrames = 0;// only recovery was done, no write at all was done
          }
          else
          {    
              logPrint("CALSAWriter: failed to recover from ALSA write error: %s (%i)", snd_strerror(alsaReadError), alsaReadError);
              ret = false;
          }
      }
  
      // 2. check current buffer load
      snd_pcm_sframes_t framesInBuffer = 0;
      snd_pcm_sframes_t delayedFrames = 0;
  
      snd_pcm_avail_delay(m_pALSAHandle, &amp;framesInBuffer, &amp;delayedFrames);
  
      // round to nearest int, cast is safe, buffer size is no bigger than uint32_t
      const int32_t ONE_HUNDRED_PERCENTS = 100;
      const uint32_t bufferLoadInPercents = ONE_HUNDRED_PERCENTS *
              static_cast&lt;int32_t&gt;(framesInBuffer) / static_cast&lt;int32_t&gt;(m_pALSACfg-&gt;alsaBufferSize);
  
      logPrint("write: ALSA buffer percentage: %u, delayed frames: %d",  bufferLoadInPercents, delayedFrames);
  
      return ret;
  }
  </code></pre>
  
  <p>Other diagnostic info: </p>
  
  <pre><code>02:53:00.465047  log info V 1 [write: ALSA buffer percentage: 75, delayed frames: 4096]
  02:53:00.635758  log info V 1 [write: ALSA buffer percentage: 74, delayed frames: 4160]
  02:53:00.805714  log info V 1 [write: ALSA buffer percentage: 74, delayed frames: 4152]
  02:53:00.976781  log info V 1 [write: ALSA buffer percentage: 74, delayed frames: 4144]
  02:53:01.147948  log info V 1 [write: ALSA buffer percentage: 0, delayed frames: 0]
  02:53:01.317113  log error V 1 [CALSAWriter WRITE FAILED for  writen farmes = -32 ]
  02:53:01.317795  log error V 1 [CALSAWriter: failed to recover from ALSA write error: Broken pipe (-32)]
  </code></pre>