* [musl] Prototypes without implementations
@ 2024-10-25 20:01 Alyssa Ross
2024-10-25 20:10 ` Rich Felker
0 siblings, 1 reply; 16+ messages in thread
From: Alyssa Ross @ 2024-10-25 20:01 UTC (permalink / raw)
To: musl
[-- Attachment #1: Type: text/plain, Size: 1415 bytes --]
<sys/io.h> includes prototypes for iopl() and ioperm(), but not all
architectures provide implementations, because the implementation is
conditionally compiled only if SYS_ioperm is defined. This means that
on aarch64, musl is providing prototypes without implementations, which
is very surprising to me.
musl provides these prototypes unconditionally since commit
0004ea613ac310daaee30c167112d796db33fa70:
> fix breakage from introducing bits header for sys/io.h
>
> apparently some other archs have sys/io.h and should not break just
> because they don't have the x86 port io functions. provide a blank
> bits/io.h everywhere for now.
Glibc only provides <sys/io.h> on alpha, ia64, i386, x86_64, of which
musl supports only the latter two. It used to provide it on arm as
well, with stub implementations (ioperm() returning ENOSYS, inb
returning 0, …), but the header was dropped in Glibc 2.30. Linux (as of
v6.11) has an ioperm syscall on x86, microblaze, mips, and powerpc, but
on everything but x86, it's just a stub that returns ENOSYS.
Some code in the wild I have found expects that it can use the existence
of <sys/io.h> as a proxy for being able to use inb/outb, etc. Would it
make sense for musl to match the Glibc behaviour of only providing
sys/io.h on i386 and x86_64? Regardless, I think that the presense of
unimplemented prototypes ought to be fixed somehow.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-25 20:01 [musl] Prototypes without implementations Alyssa Ross @ 2024-10-25 20:10 ` Rich Felker 2024-10-25 21:38 ` Alyssa Ross 0 siblings, 1 reply; 16+ messages in thread From: Rich Felker @ 2024-10-25 20:10 UTC (permalink / raw) To: Alyssa Ross; +Cc: musl On Fri, Oct 25, 2024 at 10:01:37PM +0200, Alyssa Ross wrote: > <sys/io.h> includes prototypes for iopl() and ioperm(), but not all > architectures provide implementations, because the implementation is > conditionally compiled only if SYS_ioperm is defined. This means that > on aarch64, musl is providing prototypes without implementations, which > is very surprising to me. > > musl provides these prototypes unconditionally since commit > 0004ea613ac310daaee30c167112d796db33fa70: > > > fix breakage from introducing bits header for sys/io.h > > > > apparently some other archs have sys/io.h and should not break just > > because they don't have the x86 port io functions. provide a blank > > bits/io.h everywhere for now. > > Glibc only provides <sys/io.h> on alpha, ia64, i386, x86_64, of which > musl supports only the latter two. It used to provide it on arm as > well, with stub implementations (ioperm() returning ENOSYS, inb > returning 0, …), but the header was dropped in Glibc 2.30. Linux (as of > v6.11) has an ioperm syscall on x86, microblaze, mips, and powerpc, but > on everything but x86, it's just a stub that returns ENOSYS. > > Some code in the wild I have found expects that it can use the existence > of <sys/io.h> as a proxy for being able to use inb/outb, etc. Would it > make sense for musl to match the Glibc behaviour of only providing > sys/io.h on i386 and x86_64? Regardless, I think that the presense of > unimplemented prototypes ought to be fixed somehow. Generally we aim not to provide different interfaces for different archs. That principle has only been partly followed here. I'm not sure if the status quo is preferable, or if we should add iopl/ioperm functions that just ENOSYS on archs without them, or if we should do something like you suggest and suppress them on archs that don't have/need them. But I don't really see a good motivation for the last option except trying to make badly behaving applications happy.. From the application side, using sys/io.h as proxy for existence of inb/outb is just wrong. If they want to know if inb/outb exist, they can probe those specifically: including the header and attempting to compile and link a test program that uses the interface. Rich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-25 20:10 ` Rich Felker @ 2024-10-25 21:38 ` Alyssa Ross 2024-10-26 1:21 ` Re[2]: " Laurent Bercot 0 siblings, 1 reply; 16+ messages in thread From: Alyssa Ross @ 2024-10-25 21:38 UTC (permalink / raw) To: Rich Felker; +Cc: musl [-- Attachment #1: Type: text/plain, Size: 2513 bytes --] Rich Felker <dalias@libc.org> writes: > On Fri, Oct 25, 2024 at 10:01:37PM +0200, Alyssa Ross wrote: >> <sys/io.h> includes prototypes for iopl() and ioperm(), but not all >> architectures provide implementations, because the implementation is >> conditionally compiled only if SYS_ioperm is defined. This means that >> on aarch64, musl is providing prototypes without implementations, which >> is very surprising to me. >> >> musl provides these prototypes unconditionally since commit >> 0004ea613ac310daaee30c167112d796db33fa70: >> >> > fix breakage from introducing bits header for sys/io.h >> > >> > apparently some other archs have sys/io.h and should not break just >> > because they don't have the x86 port io functions. provide a blank >> > bits/io.h everywhere for now. >> >> Glibc only provides <sys/io.h> on alpha, ia64, i386, x86_64, of which >> musl supports only the latter two. It used to provide it on arm as >> well, with stub implementations (ioperm() returning ENOSYS, inb >> returning 0, …), but the header was dropped in Glibc 2.30. Linux (as of >> v6.11) has an ioperm syscall on x86, microblaze, mips, and powerpc, but >> on everything but x86, it's just a stub that returns ENOSYS. >> >> Some code in the wild I have found expects that it can use the existence >> of <sys/io.h> as a proxy for being able to use inb/outb, etc. Would it >> make sense for musl to match the Glibc behaviour of only providing >> sys/io.h on i386 and x86_64? Regardless, I think that the presense of >> unimplemented prototypes ought to be fixed somehow. > > Generally we aim not to provide different interfaces for different > archs. That principle has only been partly followed here. I'm not sure > if the status quo is preferable, or if we should add iopl/ioperm > functions that just ENOSYS on archs without them, or if we should do > something like you suggest and suppress them on archs that don't > have/need them. But I don't really see a good motivation for the last > option except trying to make badly behaving applications happy.. I think ENOSYS is probably the way to go, especially since (via the kernel) that's already happening on some architectures. > From the application side, using sys/io.h as proxy for existence of > inb/outb is just wrong. If they want to know if inb/outb exist, they > can probe those specifically: including the header and attempting to > compile and link a test program that uses the interface. Agreed. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 832 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re[2]: [musl] Prototypes without implementations 2024-10-25 21:38 ` Alyssa Ross @ 2024-10-26 1:21 ` Laurent Bercot 2024-10-26 1:57 ` Thorsten Glaser ` (2 more replies) 0 siblings, 3 replies; 16+ messages in thread From: Laurent Bercot @ 2024-10-26 1:21 UTC (permalink / raw) To: musl >I think ENOSYS is probably the way to go, especially since (via the >kernel) that's already happening on some architectures. Note that providing ENOSYS implementations makes cross-compiling harder. When the libc provides no implementation, a sysdep test can compile and link a program using the API, and conclude that the functionality doesn't exist when the link fails. This works when cross-compiling. When the libc provides an ENOSYS implementation, the link will succeed, and a sysdep test needs to *run* a program to check that the functionality works correctly. This is not possible when cross-compiling. I'd rather have libcs omit stub implementations entirely, so that applications can test for functionality without having to run anything. Stub implementations make tests and integration of replacement implementations more difficult. (And not even only for cross builds. Looking at you, musl's utmp functions.) -- Laurent ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 1:21 ` Re[2]: " Laurent Bercot @ 2024-10-26 1:57 ` Thorsten Glaser 2024-10-26 2:11 ` Rich Felker 2024-10-26 8:26 ` Markus Wichmann 2024-10-26 10:10 ` Robert Clausecker 2 siblings, 1 reply; 16+ messages in thread From: Thorsten Glaser @ 2024-10-26 1:57 UTC (permalink / raw) To: musl On Sat, 26 Oct 2024, Laurent Bercot wrote: > I'd rather have libcs omit stub implementations entirely, so that > applications can test for functionality without having to run anything. > Stub implementations make tests and integration of replacement Fully agreed. It’s easy to make a compile+link test; my autoconf replacement depends on it (and does that right) but runtime is a whole other issue. I don’t even mind about headers declaring functions that aren’t there because only a fool tool would look at headers only… though omitting them when it’s easy to know (e.g. via cpp predefs) it’s not there is of course better. bye, //mirabilos -- 11:56⎜«liwakura:#!/bin/mksh» also, i wanted to add mksh to my own distro │ i was disappointed that there is no makefile │ but somehow the Build.sh is the least painful built system i've ever seen │ honours CC, {CPP,C,LD}FLAGS properly │ looks cleary like done by someone who knows what they are doing ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 1:57 ` Thorsten Glaser @ 2024-10-26 2:11 ` Rich Felker 0 siblings, 0 replies; 16+ messages in thread From: Rich Felker @ 2024-10-26 2:11 UTC (permalink / raw) To: Thorsten Glaser; +Cc: musl, Alyssa Ross On Sat, Oct 26, 2024 at 03:57:15AM +0200, Thorsten Glaser wrote: > On Sat, 26 Oct 2024, Laurent Bercot wrote: > > > I'd rather have libcs omit stub implementations entirely, so that > > applications can test for functionality without having to run anything. > > Stub implementations make tests and integration of replacement > > Fully agreed. It’s easy to make a compile+link test; my autoconf > replacement depends on it (and does that right) but runtime is a > whole other issue. > > I don’t even mind about headers declaring functions that aren’t > there because only a fool tool would look at headers only… though > omitting them when it’s easy to know (e.g. via cpp predefs) it’s > not there is of course better. My leaning would be not to do the ENOSYS thing, not only for this reason, but because doing so might preclude having them with a different signature on a different arch, if that were later needed. I'm not sure how realistic that happening is, but if it's plausible, it might be a good argument for moving the prototypes back to the x86-specific bits headers like I think Alyssa was proposing. OTOH it looks like some other archs already have these syscalls, and that was the motivation for the original change.. so more investigation is probably needed. Rich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 1:21 ` Re[2]: " Laurent Bercot 2024-10-26 1:57 ` Thorsten Glaser @ 2024-10-26 8:26 ` Markus Wichmann 2024-10-26 10:28 ` Re[2]: " Laurent Bercot 2024-10-26 10:10 ` Robert Clausecker 2 siblings, 1 reply; 16+ messages in thread From: Markus Wichmann @ 2024-10-26 8:26 UTC (permalink / raw) To: musl Am Sat, Oct 26, 2024 at 01:21:23AM +0000 schrieb Laurent Bercot: > When the libc provides no implementation, a sysdep test can compile > and link a program using the API, and conclude that the functionality > doesn't exist when the link fails. This works when cross-compiling. > > When the libc provides an ENOSYS implementation, the link will succeed, > and a sysdep test needs to *run* a program to check that the > functionality works correctly. This is not possible when cross-compiling. > I don't understand the remainder of the thread as it is now, because normally we consider the above behavior to be insanity. Just because a function exists in the lib does not mean it will succeed at run-time. This is already the case with functions like getrandom() or pselect(). Even if you could run run-time tests, just because it succeeds at configure time does not mean it succeeds at any later date. And conversely, just because it fails at configure time does not mean it cannot succeed. Writing your software in the above manner is therefore not sensible. Especially since the functions talked about here are system calls that on some architectures have been stubbed out in the kernel, so the run-time behavior depends on run-time kernel version. But maybe the system calls talked about here are ultra-special in some way. Ciao, Markus ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re[2]: [musl] Prototypes without implementations 2024-10-26 8:26 ` Markus Wichmann @ 2024-10-26 10:28 ` Laurent Bercot 2024-10-26 13:22 ` Markus Wichmann 0 siblings, 1 reply; 16+ messages in thread From: Laurent Bercot @ 2024-10-26 10:28 UTC (permalink / raw) To: musl >I don't understand the remainder of the thread as it is now, because >normally we consider the above behavior to be insanity. Who's "we"? > Just because a >function exists in the lib does not mean it will succeed at run-time. >This is already the case with functions like getrandom() or pselect(). getrandom() is part of the problem, yes - a function that you cannot test for at link time and that you have to make depend on a kernel version in order to use. But because the problem already exists doesn't mean it's a good idea to add to it. pselect() is posix, it has a specification. If your pselect() isn't doing what it's supposed to, then your implementation is nonconformant. Yes, nonconformant systems are ubiquitous too, that's a problem too, and that's why we test stuff, but standards are still a good thing. strlen() works everywhere and you don't need to test for it. (Yes, it's a low bar. And it's not true for strnlen(). Don't get me started.) >Even if you could run run-time tests, just because it succeeds at >configure time does not mean it succeeds at any later date. And >conversely, just because it fails at configure time does not mean it >cannot succeed. The point isn't to test for "success" or "failure" (unless you've found a solution to the halting problem, in which case I'm definitely interested). The point is to have a decent heuristic for whether a given function, identified by its name and signature, exists in your system and has a reasonable chance of doing what you think it will do. Is it perfect? No. Do we have a better way of writing portable software that does not involve starting every single executable with a battery of tests? Also no. > Writing your software in the above manner is therefore >not sensible. Every single project using a configure script such as one created by GNU autoconf, or a build system generator such as cmake or meson, is therefore not sensible. That's fair, but maybe we should still try to avoid breaking them? > Especially since the functions talked about here are >system calls that on some architectures have been stubbed out in the >kernel, so the run-time behavior depends on run-time kernel version. That's why, unfortunately, some functionality has to be documented as depending on a run-time kernel version. It would be nice if we could minimize the occurrences of having to document a dependency to a run- time libc version, too. -- Laurent ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 10:28 ` Re[2]: " Laurent Bercot @ 2024-10-26 13:22 ` Markus Wichmann 2024-10-26 22:08 ` Thorsten Glaser ` (2 more replies) 0 siblings, 3 replies; 16+ messages in thread From: Markus Wichmann @ 2024-10-26 13:22 UTC (permalink / raw) To: musl Am Sat, Oct 26, 2024 at 10:28:38AM +0000 schrieb Laurent Bercot: > Who's "we"? Me and my sockpuppet. I was under the impression that this is the general consensus among regulars on this list, as it shone through on past discussions, but maybe I'm mistaken. > > Just because a > > function exists in the lib does not mean it will succeed at run-time. > > This is already the case with functions like getrandom() or pselect(). > > getrandom() is part of the problem, yes - a function that you cannot > test for at link time and that you have to make depend on a kernel > version in order to use. But because the problem already exists doesn't > mean it's a good idea to add to it. > You call the function, and if it fails, you fall back to another method (which includes attempting to seed a PRNG with getauxval(AT_RANDOM) or trying to open /dev/urandom or the like). Does it matter if it fails because the kernel is too old or just having a bad day? I would never check the kernel version before just calling the kernel interface. > pselect() is posix, it has a specification. If your pselect() isn't > doing what it's supposed to, then your implementation is nonconformant. Failing with ENOSYS and no side effects and no wait time is conformant as well. In the case of pselect(), it is probably the better behavior of libc as well if the kernel doesn't provide the necessary syscall, because the workaround if pselect() doesn't exist is so invasive. Indeed, if you have an application that can deal with pselect() not being available, you likely have an application that doesn't need pselect() at all. (The workaround could be the self-pipe trick, which obviates the need for pselect() completely). > > Even if you could run run-time tests, just because it succeeds at > > configure time does not mean it succeeds at any later date. And > > conversely, just because it fails at configure time does not mean it > > cannot succeed. > > The point isn't to test for "success" or "failure" (unless you've > found a solution to the halting problem, in which case I'm definitely > interested). The halting problem is precisely the reason why run-time tests are a bad idea even not cross-compiling. If the function under test fails with ENOSYS, you still have no idea if that is because of a stubbed out implementation. > The point is to have a decent heuristic for whether a > given function, identified by its name and signature, exists in your > system and has a reasonable chance of doing what you think it will do. See above. Failing with ENOSYS and no side effects is a perfectly conforming implementation of most POSIX functions. > Is it perfect? No. Do we have a better way of writing portable software > that does not involve starting every single executable with a battery > of tests? Also no. > If your binary links against musl, it does do precisely those tests. Not necessarily at the start of the runtime, but inside many functions, and in many of those never saves the state about what is or is not possible in the run-time kernel, so the tests are re-run everytime the function is called. I am talking about things such as all of the socket functions on socketcall architectures attempting to do the newer syscall directly and falling back to the socketcall mechanism if that fails. Or clock_gettime(), if it cannot be implemented in VDSO, trying first the 64-bit syscall, then the 32-bit one. To me, not much difference exists between a function failing with ENOSYS and it failing for any other reason. In the end, you still simply have a function failure at run-time and need to cope with it. And it could start working at any point in the future. Maybe not in the same process lifetime, but maybe in another one. > > Writing your software in the above manner is therefore > > not sensible. > > Every single project using a configure script such as one created by > GNU autoconf, or a build system generator such as cmake or meson, is > therefore not sensible. That's fair, but maybe we should still try to > avoid breaking them? > It is possible, though not effortless, to write sensible software using any of the aforementioned build systems. I have done so with cmake at least. It does require a shift in perspective, though, to not assuming a function will be successful just because it exists. Ciao, Markus ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 13:22 ` Markus Wichmann @ 2024-10-26 22:08 ` Thorsten Glaser 2024-10-26 23:03 ` Rich Felker 2024-10-26 23:35 ` Re[2]: " Laurent Bercot 2024-10-27 22:43 ` Yao Zi 2 siblings, 1 reply; 16+ messages in thread From: Thorsten Glaser @ 2024-10-26 22:08 UTC (permalink / raw) To: musl On Sat, 26 Oct 2024, Markus Wichmann wrote: >See above. Failing with ENOSYS and no side effects is a perfectly >conforming implementation of most POSIX functions. Insisting on this ivory tower opinion will just make people mark your software as buggy and move on. For most functions, it’s reasonable to check for presence, and if so, enable codepaths that do: if (pselect(…) == -1) { if (errno == EINTR) { // special handling } err(1, "pselect"); } The vast majority of software, OSS and not, works this way. If a basic function in a standard is there it better function. Linux’ getrandom() is an offensive exception to that and better stay the only one. bye, //mirabilos -- 22:20⎜<asarch> The crazy that persists in his craziness becomes a master 22:21⎜<asarch> And the distance between the craziness and geniality is only measured by the success 18:35⎜<asarch> "Psychotics are consistently inconsistent. The essence of sanity is to be inconsistently inconsistent ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 22:08 ` Thorsten Glaser @ 2024-10-26 23:03 ` Rich Felker 2024-10-30 9:28 ` Alyssa Ross 0 siblings, 1 reply; 16+ messages in thread From: Rich Felker @ 2024-10-26 23:03 UTC (permalink / raw) To: musl On Sun, Oct 27, 2024 at 12:08:25AM +0200, Thorsten Glaser wrote: > On Sat, 26 Oct 2024, Markus Wichmann wrote: > > >See above. Failing with ENOSYS and no side effects is a perfectly > >conforming implementation of most POSIX functions. > > Insisting on this ivory tower opinion will just make people > mark your software as buggy and move on. > > For most functions, it’s reasonable to check for presence, > and if so, enable codepaths that do: > > if (pselect(…) == -1) { > if (errno == EINTR) { > // special handling > } > err(1, "pselect"); > } > > The vast majority of software, OSS and not, works this way. > If a basic function in a standard is there it better function. > > Linux’ getrandom() is an offensive exception to that and better > stay the only one. This thread has veered really off-topic. I haven't read it in full, but based on what it seems to be about, a few remarks: - I don't buy that ENOSYS buys you a license to omit parts of POSIX you don't want to implement. Yes there's license to have additional errors not defined in the standard, but the only reasonable interpretation is that these should be for concrete conditions that can be remedied. At the very least, an interface always failing is bad QoI. As an example, I don't claim running on a nommu system, where fork() will necessarily ENOSYS, gives a POSIX-conforming environment; it's a POSIX subset. IIRC part of the rationale text addresses that and agrees with my interpretation here. - pselect ENOSYS? Come on. This is 2024, almost 2025, not 1999. (Unless I'm misremembering it was added in POSIX 2001.) - Back to extension interfaces (or very recent standards) which might or might not be available at runtime: Whether availability of a particular such interface is reasonable to defer to runtime really depends on what the interface is and what it's being used for. Trying to make broad sweeping generalizations does not seem helpful, and particularly, does not seem relevant to the ioperm/iopl topic. - That said, yes, whether an interface is available at the library level, and whether it works on the machine you happen to be running on later, can differ, and this is something where "musl policy" (using the term very loosely, in the sense of what we recommend to projects when trying to get something fixed) is that, unless the standard says the interface and functionality is always present, you should both check for it at configure-time/build-time, and be prepared at runtime for the possibility that it might not be supported or might not support all features on the running system. I would expect software using iopl/ioperm already needs to be prepared for the possibility that they could fail for permissions reasons, and should avoid calling them anyway unless it knows it needs to perform userspace hardware IO. So I'm not sure how this matters or how an ENOSYS here would be any different from EPERM -- it's just another reason you can't do IO as a user process. Can we use the remainder of this thread for figuring out the real status of this (what's with non-x86 archs that have the syscalls? are they used? what about archs that don't use them? do they have you mmap a device instead?) and whether there's some action that should be taken, rather than rehashing broad philosophy? :) Rich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 23:03 ` Rich Felker @ 2024-10-30 9:28 ` Alyssa Ross 2024-10-30 12:37 ` enh 0 siblings, 1 reply; 16+ messages in thread From: Alyssa Ross @ 2024-10-30 9:28 UTC (permalink / raw) To: Rich Felker; +Cc: musl [-- Attachment #1: Type: text/plain, Size: 1691 bytes --] Rich Felker <dalias@libc.org> writes: > Can we use the remainder of this thread for figuring out the real > status of this (what's with non-x86 archs that have the syscalls? are > they used? what about archs that don't use them? do they have you mmap > a device instead?) and whether there's some action that should be > taken, rather than rehashing broad philosophy? :) On all the other architectures where musl has SYS_ioperm defined, it's mapped to sys_ni_syscall (ENOSYS), and has been at least since git was introduced. Glibc provides a fallback that uses /dev/mem on alpha, but no other architecture. In the past, it also provided an implementation for arm, which was removed in the following commit: commit 6b33f373c7b9199e00ba5fbafd94ac9bfb4337b1 Author: Florian Weimer <fweimer@redhat.com> Date: Wed May 29 16:53:09 2019 +0200 arm: Remove ioperm/iopl/inb/inw/inl/outb/outw/outl support Linux only supports the required ISA sysctls on StrongARM devices, which are armv4 and no longer tested during glibc development and probably bit-rotted by this point. (No reported test results, and the last discussion of armv4 support was in the glibc 2.19 release notes.) The functions remain on arm, but they are just ENOSYS stubs. Does any of that make it any clearer what should be done in musl to solve the prototypes without implementations problem? I guess it does make sense for musl to define __SYS_ioperm on microblaze, mips, powerpc and powerpc64 — it's in the kernel syscall table for those architectures, even though as far as I can tell it has never done anything other than return ENOSYS. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 832 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-30 9:28 ` Alyssa Ross @ 2024-10-30 12:37 ` enh 0 siblings, 0 replies; 16+ messages in thread From: enh @ 2024-10-30 12:37 UTC (permalink / raw) To: musl; +Cc: Rich Felker [-- Attachment #1: Type: text/plain, Size: 3305 bytes --] fwiw, this came up for Android recently... we'd never had the header before but the https://blog.chromium.org/2024/06/building-faster-smarter-chromebook.html work meant we needed new x86-only stuff for the first time in a decade. we basically went with this: #if defined(__NR_iopl) static __inline int ioperm(unsigned long __from, unsigned long __n, int __enabled) { return syscall(__NR_ioperm, __from, __n, __enabled); } #endif (which answers the "some architectures" part, even though for Android that's only x86/x86-64.) here's my commit message with more rationale for why i made them static inlines: """ Add <sys/io.h>. This is unusual in being inline-only, but these are (a) trivial functions, (b) ancient functions, and (c) unusable by apps. Plus they're arriving just too late for API 35, which definitely influenced by "this is silly" decision! They're also x86/x86-64 only, though that's a neutral argument because it would mean almost no-one will be affected no matter what choice we make here. There is an argument for going the usual "callers should just have their own header-only implementation that they `-include` on the compiler command line" route, but the x86/x86-64 I/O port stuff isn't going away just yet, and LTP was also already working around the absence of these. """ https://android-review.googlesource.com/c/platform/bionic/+/3135242 On Wed, Oct 30, 2024 at 5:29 AM Alyssa Ross <hi@alyssa.is> wrote: > Rich Felker <dalias@libc.org> writes: > > > Can we use the remainder of this thread for figuring out the real > > status of this (what's with non-x86 archs that have the syscalls? are > > they used? what about archs that don't use them? do they have you mmap > > a device instead?) and whether there's some action that should be > > taken, rather than rehashing broad philosophy? :) > > On all the other architectures where musl has SYS_ioperm defined, it's > mapped to sys_ni_syscall (ENOSYS), and has been at least since git was > introduced. > > Glibc provides a fallback that uses /dev/mem on alpha, but no other > architecture. In the past, it also provided an implementation for arm, > which was removed in the following commit: > > commit 6b33f373c7b9199e00ba5fbafd94ac9bfb4337b1 > Author: Florian Weimer <fweimer@redhat.com> > Date: Wed May 29 16:53:09 2019 +0200 > > arm: Remove ioperm/iopl/inb/inw/inl/outb/outw/outl support > > Linux only supports the required ISA sysctls on StrongARM > devices, > which are armv4 and no longer tested during glibc development > and probably bit-rotted by this point. (No reported test > results, > and the last discussion of armv4 support was in the glibc 2.19 > release notes.) > > The functions remain on arm, but they are just ENOSYS stubs. > > Does any of that make it any clearer what should be done in musl to > solve the prototypes without implementations problem? > > I guess it does make sense for musl to define __SYS_ioperm on > microblaze, mips, powerpc and powerpc64 — it's in the kernel syscall > table for those architectures, even though as far as I can tell it has > never done anything other than return ENOSYS. > [-- Attachment #2: Type: text/html, Size: 4281 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re[2]: [musl] Prototypes without implementations 2024-10-26 13:22 ` Markus Wichmann 2024-10-26 22:08 ` Thorsten Glaser @ 2024-10-26 23:35 ` Laurent Bercot 2024-10-27 22:43 ` Yao Zi 2 siblings, 0 replies; 16+ messages in thread From: Laurent Bercot @ 2024-10-26 23:35 UTC (permalink / raw) To: musl >You call the function, and if it fails, you fall back to another method >(which includes attempting to seed a PRNG with getauxval(AT_RANDOM) or >trying to open /dev/urandom or the like). Does it matter if it fails >because the kernel is too old or just having a bad day? That's exactly what I'm doing. That's why I have a C programming library that everything I write depends on: to wrap these excuses for interfaces into something that an application can reasonably use. It was annoying to write. And the part of the library that generates random numbers was *especially* annoying, thanks in no small part to that getrandom() behaviour. I needed 4 attempts to make it work in a satisfying way. And you're saying everyone should do that, for *every* interface exposed by the system? That is putting very unreasonable expectations on application writers, and making C even harder than people like to say it is. >Failing with ENOSYS and no side effects and no wait time is conformant >as well. Yeah. You're right. And my point, shared with other people in this thread, is that it's a bad thing, and we should avoid having these stub functions wherever possible. > (The workaround could be the self-pipe trick, which >obviates the need for pselect() completely). (Using a self-pipe is also better than pselect() for other reasons: it allows you to handle signals as regular events and process them in normal execution context rather than interruption context. So indeed pselect() is never needed, and the self-pipe trick - also implementable via signalfd() on Linux - should be the regular pattern, not a workaround.) >If the function under test fails with >ENOSYS, you still have no idea if that is because of a stubbed out >implementation. Exactly. So let's not add to the list of functions that do that. >If your binary links against musl, it does do precisely those tests. Not >necessarily at the start of the runtime, but inside many functions It is a very deliberate, very conscious choice in musl, and the explicit goal is that binaries linked against musl should run on as many kernel versions as possible, independently of the kernel version musl was built with. It is a reasonable design goal for a libc to avoid tying userspace to specific kernel features. If there is ever a place to test, live, whether a system call is supported, and fall back to a different system call, or sequence of, if it isn't, a libc would be that place; and I appreciate that musl goes to these lengths to ensure independence from the kernel. It is not, however, a reasonable expectation that *applications* should do so with the system they're running on. Applications should be able to rely on the system - that's why specifications exist. The ecosystem is already in bad enough shape that extensive build-time configuration (that works badly, and that nobody likes) is needed for most software; claiming that the sensible way of writing applications is run-time tests for system independence is abandoning any pretense of practicality. >It is possible, though not effortless, to write sensible software using >any of the aforementioned build systems. Kudos to you for making it work. Now you should know as well as I do that between writing sensible software with effort, and writing half-baked software with less effort, most of the ecosystem, including incredibly popular projects, will choose the latter. Let's not break them even more than they already are, please. -- Laurent ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 13:22 ` Markus Wichmann 2024-10-26 22:08 ` Thorsten Glaser 2024-10-26 23:35 ` Re[2]: " Laurent Bercot @ 2024-10-27 22:43 ` Yao Zi 2 siblings, 0 replies; 16+ messages in thread From: Yao Zi @ 2024-10-27 22:43 UTC (permalink / raw) To: musl On Sat, Oct 26, 2024 at 03:22:25PM +0200, Markus Wichmann wrote: > See above. Failing with ENOSYS and no side effects is a perfectly > conforming implementation of most POSIX functions. Yes, failing with ENOSYS could be conformant. But ioperm() and iopl() aren't really a POSIX thing. Why make more pitfalls instead of easing everyone's life? For stuff like ioctl(), I do agree with that standing with POSIX is correct, but in this case we aren't getting anything valuable with a stub implementation. And I think it is not a hard work to omit both the implementation and declaration on archs without these syscalls. Thanks, Yao Zi ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [musl] Prototypes without implementations 2024-10-26 1:21 ` Re[2]: " Laurent Bercot 2024-10-26 1:57 ` Thorsten Glaser 2024-10-26 8:26 ` Markus Wichmann @ 2024-10-26 10:10 ` Robert Clausecker 2 siblings, 0 replies; 16+ messages in thread From: Robert Clausecker @ 2024-10-26 10:10 UTC (permalink / raw) To: musl Am Sat, Oct 26, 2024 at 01:21:23AM +0000 schrieb Laurent Bercot: > > I think ENOSYS is probably the way to go, especially since (via the > > kernel) that's already happening on some architectures. > > Note that providing ENOSYS implementations makes cross-compiling harder. > > When the libc provides no implementation, a sysdep test can compile > and link a program using the API, and conclude that the functionality > doesn't exist when the link fails. This works when cross-compiling. > > When the libc provides an ENOSYS implementation, the link will succeed, > and a sysdep test needs to *run* a program to check that the > functionality works correctly. This is not possible when cross-compiling. > > I'd rather have libcs omit stub implementations entirely, so that > applications can test for functionality without having to run anything. > Stub implementations make tests and integration of replacement > implementations more difficult. (And not even only for cross builds. > Looking at you, musl's utmp functions.) This entire debate happened multiple times with commercial UNIX vendors some thirty years ago, who would declare all sorts of functions in their headers and define all sort of syscalls in their libc, only to then not actually implement them (they would return ENOSYS or ENOTSUPP) or only implement them if you bought some extra option. This was almost universally agreed to be a great annoyance to authors of portable software and the consensus was to avoid this stuff as much as possible. They changed things so that e.g. if you didn't buy the inet package, you just wouldn't have the header files for inet stuff installed, making it so that software could very easily detect if the feature was available or not at build time. Please don't bring back the mistakes of the past. If a function is not present, don't declare it. Failing that, don't define it. But do not define it and then just have it fail at runtime. That's a really bad move. Yours, Robert Clausecker -- () ascii ribbon campaign - for an encoding-agnostic world /\ - against html email - against proprietary attachments ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2024-10-30 12:38 UTC | newest] Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-10-25 20:01 [musl] Prototypes without implementations Alyssa Ross 2024-10-25 20:10 ` Rich Felker 2024-10-25 21:38 ` Alyssa Ross 2024-10-26 1:21 ` Re[2]: " Laurent Bercot 2024-10-26 1:57 ` Thorsten Glaser 2024-10-26 2:11 ` Rich Felker 2024-10-26 8:26 ` Markus Wichmann 2024-10-26 10:28 ` Re[2]: " Laurent Bercot 2024-10-26 13:22 ` Markus Wichmann 2024-10-26 22:08 ` Thorsten Glaser 2024-10-26 23:03 ` Rich Felker 2024-10-30 9:28 ` Alyssa Ross 2024-10-30 12:37 ` enh 2024-10-26 23:35 ` Re[2]: " Laurent Bercot 2024-10-27 22:43 ` Yao Zi 2024-10-26 10:10 ` Robert Clausecker
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/musl/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).