me wrote: >Jaroslav Kysela wrote: > >>On Wed, 12 Dec 2001, Tim Goetze wrote: >> >>> Abramo Bagnara wrote: >>> >>> >Tim Goetze wrote: >>> >> >>> >> >>but sometimes i also get inexplicable corruption within ordinary >>> >> >>dynamically allocated memory of the process before it exits. >>> >> >> >>> >> >>i have spent considerable time on verifying that these are indeed >>> >> >>caused by changing the period_size, and not by my own code. >>> >> > >>> >> >i would be too certain of this conclusion. i spent many a long night >>> >> >and day and night tracking down places in the audioengine code that >>> >> >had overrun the mmapped areas. i was only ever to track things down by >>> >> >generating huge log files that detailed every byte i wrote, and then >>> >> >use perl and awk to digest them. >>> >> > >>> >> >i'm not saying its not a problem in ALSA, only that its unlikely at >>> >> >this point. what have you done to ensure that its not your code? do >>> >> >you completely avoid writing data to the mapped areas? >>> >> > >>> >> >>> >> yes, exactly that. i just did >>> >> n * (open, configure, m * (poll, mmap_begin, mmap_commit), close) >>> >> and nothing more. >>> > >>> >You're missing avail_update: it's *mandatory*. >>> > >>> >> i ran this twice, one time with the usual configure, and one time >>> >> with f/c hardcoded to 64 in the hw setup so my code in all places believes >>> >> it's going 2048, 1024, 512, ... -- not that it matters because i don't >>> >> process any data. the one that's doing the 'real configure' crashes. >>> >>> yes, i did avail_update. sorry for not quoting all the 12111 lines of code >>> involved. >>> >>> and before i receive another message like this: i also did snd_pcm_link, >>> _unlink, _start and _drop. >> >>I think that it would be best for us to see some C code invoking the bad >>behaviour to debug the alsa-lib's code. > >so thinks me too. i've isolated the audio stream code and attached it. > >compile with 'gcc -o a.out main.cc -lasound -L/usr/lib', and run with >for example >$ ./a.out hw:0,0 2048 > >it will try to configure both streams on hw:0,0 for period_size of >2048, 1024 ... 64. on the awe it crashes when reaching 512. > >this code does not even link, start, drop or unlink - just configure >the streams. it segfaults here before exit() even if i only configured >them one time.
just in case you find C++ repelling, i've straightened it out into pure C, please find it in the attachment. no segfaulting occurs if you modify the code to setup the streams for SND_PCM_ACCESS_RW_* instead of SND_PCM_ACCESS_MMAP_*. but i guess you've already found this out. please do not interpret this as my trying to push you around -- i'm trying to understand what is going wrong myself, but reading alsa-lib code is not exactly an enlightening experience to a feeble mind like mine, and i'm wondering if you have come closer to solving the problem. tim
#include <unistd.h> #include <stdio.h> #include <alsa/asoundlib.h> void throw (char * s) { fprintf (stderr, "%s\n", s); exit (1); } typedef struct { snd_pcm_t * handle; snd_pcm_hw_params_t * hw_params; snd_pcm_sw_params_t * sw_params; } AudioStream; void AudioStream_construct (AudioStream * s) { int error; s->handle = 0; s->hw_params = 0; s->sw_params = 0; if (snd_pcm_hw_params_malloc (&s->hw_params)) throw ("hw_params_malloc fails."); if (snd_pcm_sw_params_malloc (&s->sw_params)) throw ("sw_params_malloc fails."); } void AudioStream_destruct (AudioStream * s) { if (s->handle) snd_pcm_close (s->handle); if (s->hw_params) snd_pcm_hw_params_free (s->hw_params); if (s->sw_params) snd_pcm_sw_params_free (s->sw_params); } void AudioStream_open (AudioStream *s, char * name, int type) { if (snd_pcm_open (&s->handle, name, type, 0)) throw ("pcm_open fails."); } #define CONFIGURE(what,ifnot) \ { \ int error = what; \ if (error) \ throw (ifnot); \ } void AudioStream_configure (AudioStream * s, uint sample_rate, uint frames_per_cycle) { int i; int error; int interleaved; int bytes_per_sample; int channels; snd_pcm_format_t formats [3] = { SND_PCM_FORMAT_S32, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_S8 }; CONFIGURE (snd_pcm_hw_params_any (s->handle, s->hw_params), "no 'any' configuration to start with."); CONFIGURE (snd_pcm_hw_params_set_periods_integer (s->handle, s->hw_params), "no integer period size."); error = snd_pcm_hw_params_set_access (s->handle, s->hw_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); if (error == 0) interleaved = 0; else { CONFIGURE (snd_pcm_hw_params_set_access (s->handle, s->hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED), "memory-mapped access method refused."); interleaved = 1; } /* determine sample format */ bytes_per_sample = ~0; for (i = 0; i < 3; i++) { error = snd_pcm_hw_params_set_format (s->handle, s->hw_params, formats[i]); if (error == 0) { bytes_per_sample = 4 >> i; break; } } if (bytes_per_sample > 4) throw ("none of (32, 16, 8) bit sample sizes available."); CONFIGURE (snd_pcm_hw_params_set_rate (s->handle, s->hw_params, sample_rate, 0), "unsupported sample rate."); channels = snd_pcm_hw_params_get_channels_max (s->hw_params); error = snd_pcm_hw_params_set_channels (s->handle, s->hw_params, channels); if (error) throw ("no channels available."); CONFIGURE (snd_pcm_hw_params_set_period_size (s->handle, s->hw_params, (uint) frames_per_cycle, 0), /* XXX */ "hardware refuses this frames_per_cycle setting."); CONFIGURE (snd_pcm_hw_params_set_periods (s->handle, s->hw_params, 2, 0), "hardware refuses 2 cycles per buffer."); CONFIGURE (snd_pcm_hw_params_set_buffer_size (s->handle, s->hw_params, 2 * frames_per_cycle), /* XXX */ "hardware refuses a buffer size of 2 * frames_per_cycle."); CONFIGURE (snd_pcm_hw_params (s->handle, s->hw_params), "hardware setup failed."); /* sw params */ snd_pcm_sw_params_current (s->handle, s->sw_params); CONFIGURE (snd_pcm_sw_params_set_start_threshold (s->handle, s->sw_params, ~0u), "cannot turn off start threshold."); CONFIGURE (snd_pcm_sw_params_set_stop_threshold (s->handle, s->sw_params, ~0u), "cannot turn off stop threshold."); CONFIGURE (snd_pcm_sw_params_set_silence_threshold (s->handle, s->sw_params, 0), "cannot set 0 silence threshold."); CONFIGURE (snd_pcm_sw_params_set_silence_size (s->handle, s->sw_params, 0), "cannot set 0 silence size."); CONFIGURE (snd_pcm_sw_params_set_avail_min (s->handle, s->sw_params, frames_per_cycle), "software setup for minimum available frames failed."); CONFIGURE (snd_pcm_sw_params (s->handle, s->sw_params), "software setup failed."); fprintf (stderr, "configured for %d %dbit %d %s.\n", sample_rate, 8 << bytes_per_sample, frames_per_cycle, interleaved ? "interleaved" : "linear"); } int main (int argc, char ** argv) { int fpc; if (argc != 3) throw ("give me <alsa-pcm-device-name> <initial period_size>."); if (sscanf (argv[2], "%d", &fpc) != 1) throw ("initial period_size does not seem to be a number."); while (fpc >= 64) { AudioStream capture, playback; AudioStream_construct (&capture); AudioStream_construct (&playback); AudioStream_open (&capture, argv[1], SND_PCM_STREAM_CAPTURE); AudioStream_open (&playback, argv[1], SND_PCM_STREAM_PLAYBACK); AudioStream_configure (&capture, 44100, fpc); AudioStream_configure (&playback, 44100, fpc); sleep (1); AudioStream_destruct (&capture); AudioStream_destruct (&playback); fpc >>= 1; } return 0; }