From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: Why do I get broken pipe on write to a pcm in state PREPARED? Date: Thu, 12 Sep 2002 17:56:42 +0200 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: <200209111926.g8BJQr013561@d1o87.telia.com> <200209121148.g8CBmv020843@d1o87.telia.com> Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Thu_Sep_12_17:56:42_2002-1" Return-path: In-Reply-To: <200209121148.g8CBmv020843@d1o87.telia.com> Errors-To: alsa-devel-admin@lists.sourceforge.net List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , List-Archive: To: Anders Torger Cc: alsa-devel@lists.sourceforge.net List-Id: alsa-devel@alsa-project.org --Multipart_Thu_Sep_12_17:56:42_2002-1 Content-Type: text/plain; charset=US-ASCII At Thu, 12 Sep 2002 13:48:56 +0200, Anders Torger wrote: > (...snipped the analogy of pipes...) > > Well, I have the same opinion, I'd just like to give another example > (actually the same all over again, but I want to make it obvious). For > a socket or a pipe, if noone reads from the other end, it will block > forever. Thus, a buggy program will dead-lock. I think this example > fits logically the case of writing to the sound-card but no-one starts > it. It should then block forever. agreed, although the alsa is already apart from the standard device operations (unlike normal devices, alsa needs an explicit set-up before read/write). > The problem I have is that I do not see the use of generating a broken > pipe in this situation, the only scenario I can come up with is "oh, I > got a broken pipe, I must have forgotten to start the pcm, so I do it > and try writing again". But that scenario is highly unlikely to occur > in a program, and if it does, I would call it bad programming. > > For the blocking case, however, there is a use, that of having multiple > threads (or forked processes). In my case I have a input thread and and > output thread, and the sound-card is started from the input thread, > after the output buffer has been readily filled with data. Not that it > is hard to change my program to do like ALSA wants it, but I think the > behaviour is wrong, it is not what one would expect. we can see this problem from a different angle: on the current scheme, you cannot block writing if the stream is not running. writing more in the prepare state will always return an error immediately. btw, the attached patch is a quick and untested hack to change the behavior as you wish :) please give a try. ciao, Takashi --Multipart_Thu_Sep_12_17:56:42_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="pcm-poll-fix.dif" Content-Transfer-Encoding: 7bit Index: alsa-kernel/core/pcm_lib.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_lib.c,v retrieving revision 1.19 diff -u -r1.19 pcm_lib.c --- alsa-kernel/core/pcm_lib.c 12 Aug 2002 09:45:01 -0000 1.19 +++ alsa-kernel/core/pcm_lib.c 12 Sep 2002 11:26:57 -0000 @@ -1842,14 +1842,9 @@ if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING) snd_pcm_update_hw_ptr(substream); avail = snd_pcm_playback_avail(runtime); - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED || - runtime->status->state == SNDRV_PCM_STATE_PREPARED) { - if (avail < runtime->xfer_align) { - err = -EPIPE; - goto _end_unlock; - } - } else if (((avail < runtime->control->avail_min && size > avail) || - (size >= runtime->xfer_align && avail < runtime->xfer_align))) { + if (((runtime->status->state == SNDRV_PCM_STATE_RUNNING && + avail < runtime->control->avail_min && size > avail) || + (size >= runtime->xfer_align && avail < runtime->xfer_align))) { wait_queue_t wait; enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state; if (nonblock) { @@ -1860,32 +1855,38 @@ init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->sleep, &wait); while (1) { + state = READY; set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { state = SIGNALED; break; } spin_unlock_irq(&runtime->lock); - if (schedule_timeout(10 * HZ) == 0) { - spin_lock_irq(&runtime->lock); - state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED; - break; - } + if (schedule_timeout(10 * HZ) == 0) + state = EXPIRED; spin_lock_irq(&runtime->lock); switch (runtime->status->state) { - case SNDRV_PCM_STATE_XRUN: - state = ERROR; - goto _end_loop; case SNDRV_PCM_STATE_SUSPENDED: state = SUSPENDED; goto _end_loop; - default: - break; - } - avail = snd_pcm_playback_avail(runtime); - if (avail >= runtime->control->avail_min) { + case SNDRV_PCM_STATE_PREPARED: + case SNDRV_PCM_STATE_PAUSED: state = READY; + avail = snd_pcm_playback_avail(runtime); + if (avail >= runtime->xfer_align) + goto _end_loop; break; + case SNDRV_PCM_STATE_RUNNING: + if (state != READY) + goto _end_loop; + avail = snd_pcm_playback_avail(runtime); + if (avail >= runtime->control->avail_min) + goto _end_loop; + break; + case SNDRV_PCM_STATE_XRUN: + default: + state = ERROR; + goto _end_loop; } } _end_loop: Index: alsa-kernel/core/pcm_native.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_native.c,v retrieving revision 1.22 diff -u -r1.22 pcm_native.c --- alsa-kernel/core/pcm_native.c 26 Aug 2002 10:00:17 -0000 1.22 +++ alsa-kernel/core/pcm_native.c 12 Sep 2002 11:01:14 -0000 @@ -2437,11 +2437,13 @@ mask = 0; break; case SNDRV_PCM_STATE_PREPARED: + case SNDRV_PCM_STATE_PAUSED: if (avail > 0) { mask = POLLOUT | POLLWRNORM; break; } - /* Fall through */ + mask = 0; + break; default: mask = POLLOUT | POLLWRNORM | POLLERR; break; --Multipart_Thu_Sep_12_17:56:42_2002-1-- ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf