[Toybox] FYI musl's support horizon.

Rich Felker dalias at libc.org
Fri Aug 27 15:21:41 PDT 2021


On Fri, Aug 27, 2021 at 10:21:51AM -0500, Rob Landley wrote:
> On 8/27/21 8:56 AM, Rich Felker wrote:
> > On Thu, Aug 26, 2021 at 03:56:47PM -0700, enh wrote:
> >> On Thu, Aug 26, 2021 at 2:34 PM Rob Landley <rob at landley.net> wrote:
> > 
> > Rob asked me for some input on this:
> > 
> >> > In my private emails somebody is trying to make the last aboriginal linux
> >> > release work and the old busybox isn't building anymore because makedev()
> >> > used
> >> > to be in #include <sys/types.h> and now it's moved to <sys/sysmacros.h>.
> >> > (Why? I
> >> > dunno. Third base.)
> > 
> > This was glibc bug #19239, and clearly needed to be fixed. Generic
> > lowercase macro names like "major" and "minor" are *extreme* namespace
> > pollution for a standard header to be doing.
> 
> I stared at that a bit before figuring out you were objecting because they're
> MACROS. (Generic words being FUNCTION names from headers is common: stdio.h
> defines remove(), rename(), rewind()... stdlib.h has random(), free(), abort(),
> exit()...)

Because those names are defined as being there by the C language and
expected to be there by anyone writing programs in C. Indeed, it makes
it far *worse* that major and minor were macros, since they break
things in more contexts, but if they were functions it would still be
inappropriate for sys/types.h to be exposing them.

> > sys/sysmacros.h was
> > always the correct way to get these macros on glibc, but for whatever
> > reason (compatibility with some ancient historic unices?) glibc was
> > making sys/types.h include sys/sysmacros.h implicitly, at least under
> > some profiles.
> 
> The problem is the man page said to #include <sys/types.h> to get it, so that's
> what people did.

That's unfortunate. There's been a lot of wrong stuff in man pages
but Michael is very good about taking reports and getting it
corrected.

> And even today the man page doesn't particularly call them out
> as macros, it gives them function prototypes and even calls them functions:
> 
>   The  major()  and  minor() functions perform the converse task: given a
>   device ID, they return, respectively, the major and  minor  components.

Yes. Historically they were always macros, but glibc made the macros
wrap functions because they did something more elaborate with munging
the bits to fit major and minor numbers larger than 8 bits, splitting
the extra ones across the high 48 bits...

> I thought it was like getc() being officially undecided about whether or not
> it's a macro. (Could be either way.)

Generally it's assumed that the standard headers may (at least in C,
and for standard functions) additionally define a macro anywhere a
function is specified as long as it doesn't evaluate arguments the
wrong number of times. Where the spec explicitly mentions a macro,
that means there's no obligation to avoid multiple evaluation. However
there are good reasons not to do this (breaking C++ callers, and when
the name is not a standard function, just breaking programs that don't
expect it to be there and which use the name for something else
locally.

> > What made this even worse was that, under BSD or GNU profile
> > (including by default), glibc's stdlib.h included sys/types.h. This
> > meant anything using stdlib.h got the namespace breakage.
> 
> Is it "breakage" if it's the standard for Linux and has been for years?

Yes.

> I had a function called throw() in a turbo C++ program I wrote for DOS back in
> college and a compiler upgrade turned that into a keyword and broke my stuff
> because they'd decided to gratuitously add stuff to the language AFTER I wrote
> my code. If it had been "compiling it on Linux behaves differently" I wouldn't
> have minded so much, it was a version upgrade of the same THING breaking stuff
> that bothered me.

That's why we're careful to honor the implementation's obligations on
namespace (fully in plain C or POSIX profile, and modulo well-known
extension functions in default/BSD profile). Avoiding this kind of
breakage requires both sides (implementation and application) to honor
their obligations though. If either doesn't, upgrades can break stuff.

> > In commit f552c792c7ce5a560f214e1104d93ee5b0833967 (2011) musl
> > emulated this glibc behavior in _GNU_SOURCE profile, but commit
> > a31a30a0076c284133c0f4dfa32b8b37883ac930 (2019) removed it since glibc
> > had already fixed the problem and pushed applications still depending
> > on the wrong behavior to fix their stuff.
> 
> So sys/types.h couldn't have prototyped the functions (inside #ifndef if
> necessary) and sys/macros.h couldn't have defined faster macro vesions then, and
> you get whichever one you #include first?
> 
> Eh, water over the bridge. Glibc decided to break userspace and musl fell in
> line a few years later. I'm just not convinced glibc made a good call.

No, we did something awful as a glibc compat hack back in 2011, only
in _GNU_SOURCE mode because it was so awful, and removed it after it
was no longer providing any glibc-compat. That type of hack would not
be approved to begin with nowadays.

Rich



More information about the Toybox mailing list