From 6ab4aec842dd6aa094ed7824b41ed9eba4f834b5 Mon Sep 17 00:00:00 2001 From: Krishnanand G Date: Fri, 21 Aug 2026 15:17:12 +0530 Subject: [PATCH] pcm_file: retry write(2) on short writes in safe_write() write(2) on a pipe or FIFO can return fewer bytes than requested. This happens when a blocking write gets interrupted by a signal after part of the buffer already went through: the kernel hands back the partial count instead of -EINTR. safe_write() treated any non-negative return as complete and passed that short count straight back to the caller. snd_pcm_file_write_bytes() then saw err != n, broke out of its write loop, and returned success anyway, so the unwritten tail of the period never reached the target file. Writes to a FIFO block waiting for a reader far more often than writes to a regular file do, which is exactly why the file plugin only drops samples on pipes and works fine on plain files. Make safe_write() loop until every byte is written or a real error turns up. Fixes: https://github.com/alsa-project/alsa-lib/issues/63 Signed-off-by: Krishnanand G --- src/pcm/pcm_file.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index ad8cb0db..d5ec4e48 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -102,8 +102,18 @@ typedef struct { static ssize_t safe_write(int fd, const void *buf, size_t len) { - while (1) { - ssize_t r = write(fd, buf, len); + const char *ptr = buf; + size_t left = len; + + /* + * write(2) to a pipe/FIFO is allowed to return fewer bytes than + * requested, e.g. when a blocking write is interrupted by a + * signal after part of the data has already been transferred. + * Keep retrying until everything is written (or a real error + * occurs), otherwise the caller silently drops the remainder. + */ + while (left > 0) { + ssize_t r = write(fd, ptr, left); if (r < 0) { if (errno == EINTR) continue; @@ -111,8 +121,12 @@ static ssize_t safe_write(int fd, const void *buf, size_t len) return -EIO; return -errno; } - return r; + if (r == 0) + break; + ptr += r; + left -= r; } + return len - left; } static int snd_pcm_file_append_value(char **string_p, char **index_ch_p,