Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Oct 2001 02:06:52 -0700 (PDT)
From:      Daniel Pouzzner <douzzer@mega.nu>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/31429: kernel resource deadlock on /dev/dsp
Message-ID:  <200110220906.f9M96qF22169@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         31429
>Category:       kern
>Synopsis:       kernel resource deadlock on /dev/dsp
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 22 02:10:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Daniel Pouzzner
>Release:        4.3-REL
>Organization:
www.mega.nu
>Environment:
-* uname -a
FreeBSD mega 4.3-RELEASE FreeBSD 4.3-RELEASE #9: Mon Oct 22 04:52:54 EDT 2001     douzzer@mega:/usr/src.4.3/sys/compile/MEGA  i386

>Description:
dsp_open() in sys/dev/sound/pcm/dsp.c fails to release or remember the
read channel (rdch) if the subsequent wrch allocation craps out.  This
causes all subsequent attempts to allocate the rdch to fail, because it
is already allocated (but the pointer was discarded).

>How-To-Repeat:
start sound playing with xmms or any other program that opens the dsp
read-write.  try to record sound (from the same dsp of course) - EBUSY
results.  stop sound playing.  try record again.  should work, but
instead, more EBUSYs result.

>Fix:
I'm sure you can do a cleaner job, but I just wanted to get this fixed
prontissimo:

int
dsp_open(snddev_info *d, int chan, int oflags, int devtype)
{
	pcm_channel *rdch, *wrch;
	u_int32_t fmt;

	int gotrdchthiscall = 0;

	if (chan >= d->chancount) return ENODEV;
	if ((d->flags & SD_F_SIMPLEX) && (d->ref[chan] > 0))
	  return EBUSY;
	if (d->atype[chan] != 0 && d->atype[chan] != devtype)
	  return EBUSY;

	rdch = d->arec[chan];
	wrch = d->aplay[chan];
	if (oflags & FREAD) {
		if (rdch == NULL) {
			rdch = allocchn(d, PCMDIR_REC);
			if (!rdch)
			  return EBUSY;
			gotrdchthiscall = 1;
		} else 
		  return EBUSY;
	}
	if (oflags & FWRITE) {
		if (wrch == NULL) {
			wrch = allocchn(d, PCMDIR_PLAY);
			if (!wrch) {
				if (rdch && (oflags & FREAD))
					rdch->flags &= ~CHN_F_BUSY;
				  goto busyret;
			}
		} else
		  goto busyret;
		goto nobusyret;
	busyret:
		/* must liberate the rdch if it we opened it this call */
		if (gotrdchthiscall) {
		  chn_abort(rdch);
		  rdch->flags &= ~(CHN_F_BUSY | CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
		  chn_reset(rdch, 0);
		}
		return EBUSY;
	nobusyret:
	}
[...]

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200110220906.f9M96qF22169>