Re: [asio-users] Usage of FIONBIO causes problems on FreeBSD
Brought to you by:
chris_kohlhoff
From: Vinícius d. S. O. <vin...@gm...> - 2024-04-04 12:30:43
|
The problem was partially fixed in commit https://github.com/chriskohlhoff/asio/commit/c0fbbddad10d342e9fbc6a7c13411ffedaf4bd31 However, that still causes problems for FreeBSD and other BSD systems. First, kqueue doesn't implement ioctls (FIONBIO is an ioctl), so you're still prevented from having a nested kqueue (through asio::posix::stream_descriptor) to use interfaces that are not exposed by Boost.Asio. One example of such interfaces not exposed by Boost.Asio is to await for a subprocess to finish. In FreeBSD, you have procdesc file descriptors returned by pdfork(). However you can't wait for readiness on this file descriptor. Instead, you have to watch for EVFILT_PROCDESC on kqueue: https://gitlab.com/emilua/emilua/-/blob/v0.6.0/src/freebsd/system/spawn.cpp#L111 (this code will consume 100% CPU on today's Boost.Asio because of the FIONBIO-on-the-nested-kqueue-fd bug). For other BSDs, you use NOTE_EXIT on an EVFILT_PROC instead of a EVFILT_PROCDESC to just stumble on the same Boost.Asio bug. For FreeBSD, a new workaround that is now possible due to this commit is to just call cap_ioctls_limit() on the nested kqueue file descriptor to force ENOTCAPABLE. Other BSDs can't use this workaround. I'll use this workaround in the future, but (1) other BSD systems are left to rot, and (2) this workaround doesn't solve all the problems. I don't even understand why Boost.Asio is setting non-blocking mode in a call to asio::posix::stream_descriptor::async_wait() to begin with. async_wait() is not the operation per se, but the event to wait for before doing the actual operation. Adding a fd on the set for readiness-waiting per se can't block, and neither FIONBIO nor fcntl makes any sense here. None of this current Boost.Asio behavior makes sense. Furthermore, Boost.Asio still is performing random ioctls for file descriptors that you might have received from untrusted processes. Most users won't care about it given most users control the origin of all file descriptors, but I have a project where this matters. Ideally I should be able to just disable this FIONBIO mess altogether and not worry about it ever again. And I'm still out-of-github. I asked a friend to submit a patch previously, but the patch was just ignored: https://github.com/chriskohlhoff/asio/pull/1406 (the second paragraph already explained problems not fixed in the commit that landed on the main repo, so I assume people only read the first paragraph and ignored everything else). It takes years to synchronize the supply chain across downstream distributors, so it's really frustrating to have a partially fixed patch when the original patch already fixed all the problems for the interested parties. Em qua., 6 de dez. de 2023 às 22:57, Vinícius dos Santos Oliveira <vin...@gm...> escreveu: > > I've been facing problems trying to use Github, so I can't report issues (nor send PRs) through Github. > > For now, I'll just report issues here in the list. > > In the last months I made extensive use of Boost.Asio on FreeBSD and I faced some problems. Almost all of them were related to indiscriminate usage of FIONBIO. By doing a quick search on Google I found out this ioctl() kinda predates POSIX and had inconsistent behaviour among different systems and even different objects in the same system. So it was a surprise to learn that Boost.Asio favours FIONBIO over fcntl(). > > A quick search for FIONBIO on ASIO's repo reveals it's not the first time this ioctl causes problems: https://github.com/chriskohlhoff/asio/commit/607f99ba80df71f1a96f0df71725059ee71e46ff > > For FreeBSD, the first problem I faced was related to Capsicum. Sending a Capsicum-protected file descriptor over an UNIX socket to a Boost.Asio process will block usage of ioctls on the file descriptor. The call for FIONBIO fails with ENOTCAPABLE and Boost.Asio refuses to work with the object for no good reason. > > The second problem I faced was trying to use posix::stream_descriptor to monitor a kqueue file descriptor. Boost.Asio doesn't try to support every feature the underlying system has so it offers some escape latches and posix::stream_descriptor is just one of these. However, posix::stream_descriptor will perform FIONBIO on the underlying descriptor (which of course isn't supported on kqueue file descriptors nor on many other file descriptors). This will cause async_wait() to fail. > > I think any usage of FIONBIO on Boost.Asio codebase should just be removed altogether. Recently ASIO started to require C++11 which is way way newer than fcntl() so it doesn't make sense to still depend on such problematic ioctl(). > > I have more issues to report (not all of them related to FreeBSD), but indiscriminate usage of ioctls (FIONBIO) is one that really bites my back and it's the only one I feel compelled to report sooner even if Github is playing games with me. > > > -- > Vinícius dos Santos Oliveira > https://vinipsmaker.github.io/ -- Vinícius dos Santos Oliveira https://vinipsmaker.github.io/ |