alsa-project / alsa-lib

The Advanced Linux Sound Architecture (ALSA) - library
GNU Lesser General Public License v2.1
357 stars 176 forks source link

alsalib assertion using plug+dmix #314

Open npitre opened 2 years ago

npitre commented 2 years ago

The espeak program is crashing randomly here. I've been able to isolate the issue in a small test program demonstrating the crash 100% of the time, ending in:

alsa_quickcrash: pcm.c:3236: snd_pcm_area_copy: Assertion `src < dst || src >= dst + bytes' failed.
Aborted (core dumped)

Here's the test code:

/* to compile: gcc -O2 -Wall -o alsa_quickcrash alsa_quickcrash.c -lasound */

#include <alsa/asoundlib.h>
#include <stdio.h>
#include <string.h>

#define DEVICE "test_dummy"
#define RATE 22050
#define CHANNELS 1
#define FORMAT SND_PCM_FORMAT_S16_LE
#define BUF_MS 60

#define DO(x) if (x < 0) { fprintf(stderr, "%s failed\n", #x); exit(1); }

int main()
{
    unsigned int rate = RATE;
    snd_pcm_uframes_t frames = RATE * BUF_MS / 1000;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;

    DO(snd_pcm_hw_params_malloc(&params));
    DO(snd_pcm_open(&handle, DEVICE, SND_PCM_STREAM_PLAYBACK, 0));
    DO(snd_pcm_hw_params_any(handle, params));
    DO(snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED));
    DO(snd_pcm_hw_params_set_format(handle, params, FORMAT));
    DO(snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0));
    DO(snd_pcm_hw_params_set_channels(handle, params, CHANNELS));
    DO(snd_pcm_hw_params_set_buffer_size_near(handle, params, &frames));
    DO(snd_pcm_hw_params(handle, params));
    DO(snd_pcm_prepare(handle));

    printf("PCM config dump:\n");
    snd_output_t *output = NULL;
    DO(snd_output_stdio_attach(&output, stdout, 0));
    DO(snd_pcm_dump(handle, output));
    printf("\n");

    printf("frames = %ld\n", (long)frames);
    short data[frames * CHANNELS];
    memset(data, 0, sizeof(data));

    printf("writing whole buffer\n");
    DO(snd_pcm_writei(handle, data, frames));
    printf("writing whole buffer\n");
    DO(snd_pcm_writei(handle, data, frames));
    printf("writing whole buffer minus 1 frame\n");
    DO(snd_pcm_writei(handle, data, frames - 1));

    printf("draining audio\n");
    DO(snd_pcm_drain(handle));

    printf("done\n");
    DO(snd_pcm_close(handle));
    return 0;
}

Here's the corresponding .asoundrc content:

pcm.test_dummy {
    type plug
    slave.pcm "mix_dummy"
}

pcm.mix_dummy {
    type dmix
    ipc_key 1024
    ipc_key_add_uid false
    ipc_perm 0666
    slave {
        pcm "hw:0"
        period_size 1024
        buffer_size 4096
        format "S16_LE"
        rate 48000
    }
}

And here's the complete test output:

PCM config dump:
Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)
Converter: linear-interpolation
Protocol version: 10003
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 22050
  exact rate   : 22050 (22050/1)
  msbits       : 16
  buffer_size  : 1411
  period_size  : 470
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 470
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 1411
  silence_threshold: 0
  silence_size : 0
  boundary     : 3177289537109884928
Slave: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0
    1 <- 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 3072
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 2
  stop_threshold   : 3072
  silence_threshold: 0
  silence_size : 0
  boundary     : 6917529027641081856
Slave: Direct Stream Mixing PCM
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 3072
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 2
  stop_threshold   : 3072
  silence_threshold: 0
  silence_size : 0
  boundary     : 6917529027641081856
Hardware PCM card 1 'HDA Intel PCH' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 4096
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : ENABLE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 0
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 2734916609

frames = 1411
writing whole buffer
writing whole buffer
writing whole buffer minus 1 frame
draining audio
alsa_quickcrash: pcm.c:3236: snd_pcm_area_copy: Assertion `src < dst || src >= dst + bytes' failed.
Aborted (core dumped)