Subject: kern/1186: can't interrupt process hung on audio output
To: None <gnats-admin@sun-lamp.pc.cs.cmu.edu>
From: John Kohl <jtk@kolvir.blrc.ma.us>
List: netbsd-bugs
Date: 07/02/1995 15:50:06
>Number: 1186
>Category: kern
>Synopsis: processes interrupted from writing to audio cannot be reinterrupted during exit
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Jul 2 15:50:05 1995
>Originator: John Kohl
>Organization:
NetBSD Kernel Hackers `R` Us
>Release: -current, June 30
>Environment:
System: NetBSD kolvir 1.0A NetBSD 1.0A (KOLVIR) #559: Sun Jul 2 14:50:32 EDT 1995 jtk@kolvir:/u1/NetBSD-current/src/sys/arch/i386/compile/KOLVIR i386
>Description:
If you have a buggy sound driver, and a process is stuck inside
audio_write, you can interrupt it and it will then start cleaning up/exiting.
While it's exiting, it has all signals masked and it cannot be
interrupted when it tries to drain the audio output.
>How-To-Repeat:
Get a buggy driver. Interrupt a process writing to the sound card, and
try to interrupt it while it's exiting.
>Fix:
Make the audio_drain routine time out after some period of time. In the
patch below, I set it to 60 seconds.
===================================================================
RCS file: RCS/audio.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 audio.c
--- audio.c 1995/06/06 03:53:56 1.1.1.1
+++ audio.c 1995/07/02 19:18:25
@@ -76,12 +76,13 @@
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/syslog.h>
+#include <sys/kernel.h>
#include <sys/audioio.h>
#include <dev/audiovar.h>
#include <dev/audio_if.h>
#ifdef DEBUG
#include <machine/stdarg.h>
#ifndef TOLOG
#define TOLOG 0x04
@@ -451,9 +452,10 @@
}
static inline int
-audio_sleep(chan, label)
+audio_sleep_timo(chan, label, timo)
int *chan;
char *label;
+ int timo;
{
int st;
@@ -461,11 +463,22 @@
label = "audio";
*chan = 1;
- st = (tsleep(chan, PWAIT | PCATCH, label, 0));
+ st = (tsleep(chan, PWAIT | PCATCH, label, timo));
*chan = 0;
+ if (st != 0) {
+ DPRINTF(("audio_sleep: %d\n", st));
+ }
return (st);
}
+static inline int
+audio_sleep(chan, label)
+ int *chan;
+ char *label;
+{
+ return audio_sleep_timo(chan, label, 0);
+}
+
static inline void
audio_wakeup(chan)
int *chan;
@@ -602,7 +615,8 @@
int s = splaudio();
sc->sc_mode |= 1<<AUMODE_RECORD;
- if (sc->hw_if->speaker_ctl)
+ if (sc->hw_if->speaker_ctl &&
+ (!sc->hw_if->full_duplex || (sc->sc_mode & 1<<AUMODE_PLAY) == 0))
sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_OFF);
splx(s);
}
@@ -631,7 +645,13 @@
while (sc->pr.nblk > 0) {
DPRINTF(("audio_drain: nblk=%d\n", sc->pr.nblk));
- error = audio_sleep(&sc->sc_wchan, "aud dr");
+ /*
+ * XXX
+ * When the process is exiting, it ignores all signals and
+ * we can't interrupt this sleep, so we set a 1-minute
+ * timeout.
+ */
+ error = audio_sleep_timo(&sc->sc_wchan, "aud dr", 60*hz);
if (error != 0)
return (error);
}
>Audit-Trail:
>Unformatted: