[xiph-cvs] cvs commit: ao/src/plugins/oss ao_oss.c
Stan Seibert
volsung at xiph.org
Sun Aug 12 08:12:46 PDT 2001
volsung 01/08/12 08:12:45
Modified: src/plugins/oss ao_oss.c
Log:
Changed the way we open the dsp to prevent deadlock if another program
opens the dsp between plugin_test() and plugin_open(). Now we always
open it with O_NONBLOCK and remove the blocking later if needed. The
ALSA docs claim that this is required by the OSS spec, but that is
not so obvious.
Revision Changes Path
1.10 +35 -17 ao/src/plugins/oss/ao_oss.c
Index: ao_oss.c
===================================================================
RCS file: /usr/local/cvsroot/ao/src/plugins/oss/ao_oss.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ao_oss.c 2001/08/10 00:32:20 1.9
+++ ao_oss.c 2001/08/12 15:12:45 1.10
@@ -68,39 +68,57 @@
* open either the devfs device or the traditional device and return a
* file handle. Also strdup() path to the selected device into
* *dev_path. Assumes that *dev_path does not need to be free()'ed
- * initially. The extra_open_flags allows additional flags to be
- * passed to open() if needed.
+ * initially.
+ *
+ * This opens the device in non-blocking mode at first in order to prevent
+ * deadlock caused by ALSA's OSS emulation and some OSS drivers if the
+ * device is already in use. If blocking is non-zero, we remove the blocking
+ * flag if possible so that the device can be used for actual output.
*/
-int _open_default_oss_device (char **dev_path, int extra_open_flags)
+int _open_default_oss_device (char **dev_path, int blocking)
{
int fd;
+ char *err = NULL;
+ char *dev = NULL;
/* default: first try the devfs path */
*dev_path = strdup("/dev/sound/dsp");
- fd = open(*dev_path, O_WRONLY | extra_open_flags);
+ fd = open(*dev_path, O_WRONLY | O_NONBLOCK);
+ /* then try the original dsp path */
if(fd < 0)
{
/* no? then try the traditional path */
- char *err = strdup(strerror(errno));
- char *dev = strdup(*dev_path);
+ err = strdup(strerror(errno));
+ dev = strdup(*dev_path);
free(*dev_path);
*dev_path = strdup("/dev/dsp");
- fd = open(*dev_path, O_WRONLY | extra_open_flags);
+ fd = open(*dev_path, O_WRONLY | O_NONBLOCK);
+ }
+
+ /* Now have to remove the O_NONBLOCK flag if so instructed. */
+ if (fd > 0 && blocking) {
+ if (fcntl(fd, F_SETFL, 0) < 0) { /* Remove O_NONBLOCK */
+ /* If we can't go to blocking mode, we can't use
+ this device */
+ close(fd);
+ fd = -1;
+ }
+ }
- if(fd < 0)
- {
- /* fprintf(stderr,
+ /* Deal with error cases */
+ if(fd < 0)
+ {
+ /* fprintf(stderr,
"libao - error: Could not open either default device:\n"
" %s - %s\n"
" %s - %s\n",
err, dev,
strerror(errno), *dev_path); */
- free(err);
- free(dev);
- free(*dev_path);
- *dev_path = NULL;
- }
+ free(err);
+ free(dev);
+ free(*dev_path);
+ *dev_path = NULL;
}
return fd;
@@ -117,7 +135,7 @@
driver detection unless the O_NONBLOCK flag is passed to
open(). We cannot use this flag when we actually open the
device for writing because then we will overflow the buffer. */
- if ( (fd = _open_default_oss_device(&dev_path, O_NONBLOCK)) < 0 )
+ if ( (fd = _open_default_oss_device(&dev_path, 0)) < 0 )
return 0; /* Cannot use this plugin with default parameters */
else {
free(dev_path);
@@ -185,7 +203,7 @@
}
} else {
- internal->fd = _open_default_oss_device(&internal->dev, 0);
+ internal->fd = _open_default_oss_device(&internal->dev, 1);
if (internal->fd < 0)
return 0; /* Cannot open default device */
}
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list