[Bug 289441] /dev/dsp O_NONBLOCK flag effective when set by fctnl(), ineffective when set by open()

From: <bugzilla-noreply_at_freebsd.org>
Date: Wed, 10 Sep 2025 17:26:59 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=289441

            Bug ID: 289441
           Summary: /dev/dsp O_NONBLOCK flag effective when set by
                    fctnl(), ineffective when set by open()
           Product: Base System
           Version: 14.3-RELEASE
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: damjan.jov@gmail.com

Here, the O_NONBLOCK flag is set by the open() call, and the fcntl() with
F_GETFL proves it is set, but write() will still block:

---snip---
int audio_fd, ret;
audio_fd = open("/dev/dsp", O_WRONLY | O_NONBLOCK, 0);
ret = fcntl(audio_fd, F_GETFL, 0);
printf("flag = 0x%08x\n", ret);
ret = write(audio_fd, ..., ...);
---snip---

However, if O_NONBLOCK is set by fcntl() with F_SETFL, then write() becomes
non-blocking, correctly returning -1 with errno==EAGAIN when the buffer is
full, instead of blocking:

---snip---
int audio_fd, ret;
audio_fd = open("/dev/dsp", O_WRONLY, 0);
ret = fcntl(audio_fd, F_SETFL, O_NONBLOCK);
ret = fcntl(audio_fd, F_GETFL, 0);
printf("flag = 0x%08x\n", ret);
ret = write(audio_fd, ..., ...);
---snip---

The same value ("flag = 0x00000005") is printed out in both cases by printf(),
but it is only effective in actually making write() non-blocking when set by
fcntl() with F_SETFL, it does nothing when it's set by open().

Do any real applications pass O_NONBLOCK in open()? Yes, at least Wine does, in
file dlls/wineoss.drv/oss.c. This could be the cause of several sound bugs with
Wine on FreeBSD.

-- 
You are receiving this mail because:
You are the assignee for the bug.