From owner-freebsd-bugs@FreeBSD.ORG Mon Dec 3 11:10:01 2007 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3929016A47B for ; Mon, 3 Dec 2007 11:10:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 16A5713C45D for ; Mon, 3 Dec 2007 11:10:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id lB3BA08R007705 for ; Mon, 3 Dec 2007 11:10:00 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id lB3BA0Sd007704; Mon, 3 Dec 2007 11:10:00 GMT (envelope-from gnats) Resent-Date: Mon, 3 Dec 2007 11:10:00 GMT Resent-Message-Id: <200712031110.lB3BA0Sd007704@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Henrik Gulbrandsen Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1DE4B16A41A for ; Mon, 3 Dec 2007 11:01:41 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 102F413C4CC for ; Mon, 3 Dec 2007 11:01:41 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.2/8.14.2) with ESMTP id lB3B1Md3025883 for ; Mon, 3 Dec 2007 11:01:22 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.2/8.14.1/Submit) id lB3B1MaR025882; Mon, 3 Dec 2007 11:01:22 GMT (envelope-from nobody) Message-Id: <200712031101.lB3B1MaR025882@www.freebsd.org> Date: Mon, 3 Dec 2007 11:01:22 GMT From: Henrik Gulbrandsen To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/118395: [patch] Audio playback aborted with SNDCTL_DSP_SETTRIGGER X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Dec 2007 11:10:01 -0000 >Number: 118395 >Category: kern >Synopsis: [patch] Audio playback aborted with SNDCTL_DSP_SETTRIGGER >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Dec 03 11:10:00 UTC 2007 >Closed-Date: >Last-Modified: >Originator: Henrik Gulbrandsen >Release: 7.0-BETA3 >Organization: >Environment: FreeBSD Particle 7.0-BETA3 FreeBSD 7.0-BETA3 #2: Sat Dec 1 18:11:51 CET 2007 henrik@Particle:/usr/src/sys/i386/compile/GENERIC i386 >Description: Revision 1.121 of src/sys/dev/sound/pcm/channel.c introduced incorrect handling of the SNDCTL_DSP_SETTRIGGER ioctl request. Normally, this request allows users to delay the start of audio playback until the output buffer has been filled, as documented at pages 104-105 of http://www.opensound.com/pguide/oss.pdf. Current FreeBSD code interprets the blocked channel as an error and aborts playback. This bug affects version 19 of PortAudio (the audio/portaudio2 port) and may be the reason why the audio/audacity-devel port is explicitly configured with the older version 18 of PortAudio. >How-To-Repeat: The attached shell archive includes the trigger.c example program, which fails under FreeBSD 7.0-BETA3: Particle$ ./trigger Failed second SNDCTL_DSP_SETTRIGGER: Invalid argument Particle$ >Fix: The attached shell archive also includes the channel.c.patch file, which fixes the problem: Particle$ ./trigger Everything worked. Particle$ The patch also includes a corresponding fix for the recording case, which I have not actually tested. Judging from code and documentation, it should be handled in exactly the same way, though. Patch attached with submission follows: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # trigger.c # channel.c.patch # echo x - trigger.c sed 's/^X//' >trigger.c << 'END-of-trigger.c' X#include X#include X#include X#include X#include X#include X Xint main(int argc, char *argv[]) X{ X int dev, flags, enable_bits; X char buffer[1024]; X X memset(buffer, 0, sizeof(buffer)); X X dev = open("/dev/dsp", O_WRONLY); X if (dev == -1) { X perror("Failed open"); X return EXIT_FAILURE; X } X X flags = fcntl(dev, F_GETFL); X if (flags == -1) { X perror("Failed F_GETFL"); X return EXIT_FAILURE; X } X X flags |= O_NONBLOCK; X X if (fcntl(dev, F_SETFL, flags) == -1) { X perror("Failed F_SETFL"); X return EXIT_FAILURE; X } X X enable_bits = ~PCM_ENABLE_OUTPUT; X if (ioctl(dev, SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1) { X perror("Failed first SNDCTL_DSP_SETTRIGGER"); X return EXIT_FAILURE; X } X X while (write(dev, buffer, sizeof(buffer)) != -1) { X /* Nothing */ X } X X if (errno != EAGAIN) { X perror("Unexpected write error"); X return EXIT_FAILURE; X } X X enable_bits = PCM_ENABLE_OUTPUT; X if (ioctl(dev, SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1) { X perror("Failed second SNDCTL_DSP_SETTRIGGER"); X return EXIT_FAILURE; X } X X printf("Everything worked.\n"); X return EXIT_SUCCESS; X} END-of-trigger.c echo x - channel.c.patch sed 's/^X//' >channel.c.patch << 'END-of-channel.c.patch' X--- sys/dev/sound/pcm/channel.c.orig 2007-06-16 05:37:28.000000000 +0200 X+++ sys/dev/sound/pcm/channel.c 2007-12-03 10:53:48.000000000 +0100 X@@ -409,7 +409,7 @@ X sndbuf_acquire(bs, NULL, t); X } X ret = 0; X- if (CHN_STOPPED(c)) { X+ if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) { X ret = chn_start(c, 0); X if (ret != 0) X c->flags |= CHN_F_DEAD; X@@ -520,7 +520,7 @@ X X CHN_LOCKASSERT(c); X X- if (CHN_STOPPED(c)) { X+ if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) { X ret = chn_start(c, 0); X if (ret != 0) { X c->flags |= CHN_F_DEAD; END-of-channel.c.patch exit >Release-Note: >Audit-Trail: >Unformatted: