[alsa-devel] [PATCH 1/2] pcm_file: do not disrupt playback on output file write fail
Cezary Rojewski
cezary.rojewski at intel.com
Sat Jun 8 20:38:07 CEST 2019
On 2019-06-07 14:23, Adam Miartus wrote:
> previously playback could be interrupted by snd_pcm_file_add_frames:
> assert(file->wbuf_used_bytes < file->wbuf_size_bytes)
>
> in case snd_pcm_file_write_bytes fails to write full amount of bytes
> to file, variable wbuf_used_bytes would not be fully decremented by
> requested amount of bytes function was called with
>
> for the assert to trigger, multiple write fails need to happen, so
> that wbuf_used_bytes overflows wbuf_size_bytes,
>
> this patch will allow application to report error code to api user
> who might have an idea how to recover, before assert is triggered,
> also reporting error along with the print out message might give user
> a better idea of what is going on, where previously reason for
> mentioned assert was not immediately clear
>
> Signed-off-by: Adam Miartus <amiartus at de.adit-jv.com>
> ---
> src/pcm/pcm_file.c | 36 ++++++++++++++++++++++++------------
> 1 file changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c
> index 1ef80b5..a1d15d6 100644
> --- a/src/pcm/pcm_file.c
> +++ b/src/pcm/pcm_file.c
> @@ -381,27 +381,31 @@ static void fixup_wav_header(snd_pcm_t *pcm)
>
>
>
> -static void snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes)
> +/* return error code in case write failed */
> +static int snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes)
> {
> snd_pcm_file_t *file = pcm->private_data;
> + snd_pcm_sframes_t err = 0;
> assert(bytes <= file->wbuf_used_bytes);
>
> if (file->format == SND_PCM_FILE_FORMAT_WAV &&
> !file->wav_header.fmt) {
> - if (write_wav_header(pcm) < 0)
> - return;
> + err = write_wav_header(pcm);
> + if (err < 0) {
> + SYSERR("%s write failed, file data may be corrupt", file->fname);
> + return err;
> + }
write_wav_header already dumps "Write error" on failure. Both messages
are quite similar. Your message dumps filename though, so it's clearly
more descriptive - consider updating write_wav_header SYSERR message all
along while simplifying code here.
> }
>
> while (bytes > 0) {
> - snd_pcm_sframes_t err;
> size_t n = bytes;
> size_t cont = file->wbuf_size_bytes - file->file_ptr_bytes;
> if (n > cont)
> n = cont;
> err = write(file->fd, file->wbuf + file->file_ptr_bytes, n);
> if (err < 0) {
> - SYSERR("write failed");
> - break;
> + SYSERR("%s write failed, file data may be corrupt", file->fname);
> + return err;
> }
> bytes -= err;
> file->wbuf_used_bytes -= err;
> @@ -412,15 +416,18 @@ static void snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes)
> if ((snd_pcm_uframes_t)err != n)
> break;
> }
> +
> + return 0;
> }
>
> -static void snd_pcm_file_add_frames(snd_pcm_t *pcm,
> - const snd_pcm_channel_area_t *areas,
> - snd_pcm_uframes_t offset,
> - snd_pcm_uframes_t frames)
> +static int snd_pcm_file_add_frames(snd_pcm_t *pcm,
> + const snd_pcm_channel_area_t *areas,
> + snd_pcm_uframes_t offset,
> + snd_pcm_uframes_t frames)
> {
> snd_pcm_file_t *file = pcm->private_data;
> while (frames > 0) {
> + int err = 0;
> snd_pcm_uframes_t n = frames;
> snd_pcm_uframes_t cont = file->wbuf_size - file->appl_ptr;
> snd_pcm_uframes_t avail = file->wbuf_size - snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes);
> @@ -437,10 +444,15 @@ static void snd_pcm_file_add_frames(snd_pcm_t *pcm,
> if (file->appl_ptr == file->wbuf_size)
> file->appl_ptr = 0;
> file->wbuf_used_bytes += snd_pcm_frames_to_bytes(pcm, n);
> - if (file->wbuf_used_bytes > file->buffer_bytes)
> - snd_pcm_file_write_bytes(pcm, file->wbuf_used_bytes - file->buffer_bytes);
> + if (file->wbuf_used_bytes > file->buffer_bytes) {
> + err = snd_pcm_file_write_bytes(pcm, file->wbuf_used_bytes - file->buffer_bytes);
> + if (err < 0) {
> + return err;
> + }
Suggestion: drop unnecessary brackets.
> + }
> assert(file->wbuf_used_bytes < file->wbuf_size_bytes);
> }
> + return 0;
Hmm. For snd_pcm_file_write_bytes you've chosen a different form:
newline + return. Code looks more cohesive if it's "formatted" in the
same fashion.
> }
>
> static int snd_pcm_file_close(snd_pcm_t *pcm)
>
More information about the Alsa-devel
mailing list