6 ms·
That musl refuses to implement dlclose() says it all, really. Musl's sin isn't all that different from old glibc's, really: both forget that the system serves p
by quotemstr 7y ago
That musl refuses to implement dlclose() says it all, really. Musl's sin isn't all that different from old glibc's, really: both forget that the system serves programs, not the other way around. The musl author doesn't believe programs should unload code. Therefore, you're not allowed to do it.
Musl also removed access to Linux functionality because the author disagrees with the kernel's design:
"linux's sched_* syscalls actually implement the TPS (thread
scheduling) functionality, not the PS (process scheduling)
functionality which the sched_* functions are supposed to have.
omitting support for the PS option (and having the sched_* interfaces
fail with ENOSYS rather than omitting them, since some broken software
assumes they exist) seems to be the only conforming way to do this on
linux."
LOL. Do you really want to depend on a libc whose author thinks this way? Who removes functionality that the kernel provides because in his opinion the kernel's design is wrong?
- 0xcde4c3db 7y ago> The musl author doesn't believe programs should unload code. Therefore, you're not allowed to do it. Where did you get this? A rationale is given at [1], and it's basically: 1) dlclose() being a no-op is allowed by POSIX. 2) It's common for unloading and reloading libraries to trigger subtle/latent bugs, so making dlclose() a no-op leads to more reliable operation in the common case. 3) Managing thread-local storage in combination with unloading libraries is a complex problem, and arguably requires libc to either weaken error handling or leak memory. This is certainly consistent with an opinionated-standards-lawyer-curmudgeon view of the world, but it seems pretty far from just saying that you're not allowed to do it because you shouldn't. [1] https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries https://wiki.musl-libc.org/functional-differences-from-glibc...
- quotemstr 7y agoYet the bumblebee flies: other libc implementations successfully implement code unloading and no amount of pointing at the standard will make me okay with musl not implementing code unloading, especially when part of the rationale is that other people write buggy code. It's not the place of libc to break functionality because the author believes other programmers can't use that functionality correctly.
- wahern 7y agoWhich ones? Last time I looked that list couldn't have included glibc, which while nominally supporting it had several, long-standing thread race bugs. The nexus of dynamic library loading and threading is a hot-spot for bugs in glibc.[1] Excluding an interface is better than providing a buggy one, IMO. [1] What glibc needs to do is finally merge libpthread into libc proper. The amount of stub functions, conditional logic, mutex reimplementation, and other chicanery glibc implements in an attempt to support runtime loading of libpthread[2] makes the code extremely difficult to navigate and debug. Which IME goes a long way toward explaining why there are years of unfixed races in glibc. [2] By runtime I mean loading libpthread as a dependency of a shared library where the main binary wasn't linked against libpthread.
- quotemstr 7y ago> nominally supporting it had several, long-standing thread race bugs Name one. And yes, pthreads should just be part of libc. Separating them is artificial and awkward.
- wahern 7y agoI'm lazy so it's not specific to dlclose and unloading, here's one for dlerror I submitted in 2015 and which is still open: https://sourceware.org/bugzilla/show_bug.cgi?id=18192 https://sourceware.org/bugzilla/show_bug.cgi?id=18192 I also point in that report to three other similar races which I didn't have the time to properly document (because, seriously, they're so numerous and the backlog so long, it's hard not to be cynical).[1] Look, I like glibc. I applaud their focus on ABI compatibility. glibc is burdened by tremendous technical debt, much of it blameless. And the project doesn't see the investment and attention it should. musl by contrast is a breath of fresh air in terms of correctness and simplicity, but they achieve that in part by taking a different approach than glibc. And that approach isn't necessarily better, it's just different, and they each have their costs. Pick your poison. [1] And I don't like drive-by complaints. If I submit a ticket for a project I try to back it with substantial evidence and suggested remedies, such as this Python2 + FIPS OpenSSL bug analysis I submitted last year: https://bugs.launchpad.net/ubuntu/+source/python2.7/+bug/1835135 https://bugs.launchpad.net/ubuntu/+source/python2.7/+bug/183... This is especially important for projects like glibc which are drowning in open bug reports.
- jfkebwjsbx 7y agoPretty much 2) is saying "you're not allowed to do it because you shouldn't"...
- naasking 7y agoActually, it seems pretty consistent with the original point that "the system serves programs, not the other way around". dlopen() being a no-op means the system is more reliable, so it sounds like the right choice.
- mrpippy 7y agoApple has also considered making dlclose() a no-op on non-macOS (and the presentation is 3 years old so it may have happened by now) https://news.ycombinator.com/item?id=20229723 https://news.ycombinator.com/item?id=20229723
- saagarjha 7y agoNo, dlclose still unloads the image if the reference count reaches 0: https://github.com/apple-open-source-mirror/dyld/blob/f033f5564c85c5cbfd24cf25e702e4bb0c2c39b4/dyld3/APIs.cpp#L795 https://github.com/apple-open-source-mirror/dyld/blob/f033f5...
- AnssiH 7y ago> Who removes functionality that the kernel provides because in his opinion the kernel's design is wrong? The functionality is still available via pthread sched functions as specified by POSIX, so I'd argue that functionality was not removed, just moved: https://git.musl-libc.org/cgit/musl/commit/?id=1e21e78bf7a5 https://git.musl-libc.org/cgit/musl/commit/?id=1e21e78bf7a5 IMHO this makes sense for a libc that explicitly emphasizes POSIX-correctness. POSIX defines these functions, and it is against the spec to have process scheduling functions work as thread scheduling functions (which are a separate set of functions in POSIX). edit: Just realized that this might prevent changing scheduling parameters of another process by PID, though.
- rrss 7y agoThe sched_* functions, as implemented by glibc, do not do what POSIX says they should. On linux, it is not possible to implement them in a way that is compliant with the standard, so musl does not implement them. Given the principles specified in this webpage, that seems like a pretty reasonable thing to do. musl does expose the extent of functionality provided by the kernel through the corresponding pthread scheduling functions. > Who removes functionality that the kernel provides because in his opinion the kernel's design is wrong? The kernel doesn't provide the necessary functionality. The functionality that the kernel does provide is still available in musl. I can understand that this is probably frustrating (I'm sure I would be frustrated if I had to deal with it), but I can respect musl's decision not to have sched_* do the wrong thing.
- naasking 7y ago> I can respect musl's decision not to have sched_* do the wrong thing. Particularly because this actually ensures that programs linked to musl are 100% portable (modulo bugs), rather than introducing subtle platform incompatibilities due to slightly differing platform semantics.
- seemslegit 7y agoYou seem to either forget or not be aware in the first place that the purpose of libc and posix is to allow portability between different operating systems, so it makes complete sense that linux-specific capabilities are not exposed, it has nothing to do with disagreement about kernel design.
- quotemstr 7y agoNo, that is not the primary purpose of libc. The primary purpose of libc is to run programs that the user wants to run, and removing random things make that harder. Whether the standard allows something is irrelevant: what matters is whether any given change is good for the user.
- seemslegit 7y agoThis says absolutely nothing, for any given change you can find a user who benefits from it and a user who doesn't, hence a coordination device called a standard has been invented.
- cryptonector 7y agoExcept that the whole Linux ecosystem, starting with the kernel and going from there, simply doesn't really care about POSIX. Now, that Musl does is... well, would have been, long ago... a breath of fresh air. But the ship has sailed. The Linux kernel ABI has won. Solaris, Illumos, the *BSDs, Windows -- all tried to emulate the Linux kernel ABI, and could not do a good enough job, so they all pretty much abandoned the project. The Linux kernel ABI won and that's that. Well, if we could convince devs that static linking is bad... But even then, the Linux kernel ABI leaks for all sorts of things, starting with /proc. And yes, static linking is bad, for a variety of reasons, the biggest of which is that static linking is stuck with 1970s semantics that suck because accidental symbol interposition happens all too easily. That doesn't mean that static linking couldn't grow ELF-like semantics, but if it hasn't over the past 40+ years... Still, even assuming that, there would be other reasons not to love static linking. If we could convince people to ship only dynamically-linked executables, then the ABI to emulate would be smaller, but still huge.
- wahern 7y ago> LOL. Do you really want to depend on a libc whose author thinks this way? Who removes functionality that the kernel provides because in his opinion the kernel's design is wrong? musl can't remove the functionality provided by the kernel. You're still free to use syscall(3) or otherwise invoke the kernel routine yourself. May I assume you abstained from using glibc prior to 2.30 on account of glibc not providing a wrapper for the gettid syscall? More apropos: do you dislike how glibc and musl both change the behavior of Linux setuid syscall to make it standards-conformant--process-global instead of thread-local? Should they simply provide the Linux semantics rather than the standard semantics? Has the kernel no culpability here for not providing the necessary interfaces for implementing the standard-compliant semantics?