On Sun, Jun 17, 2012 at 10:56:48PM +0200, Bruno Haible wrote:
> Rich Felker wrote:
> > 1. freadahead is inherently non-portable and has no working portable
> > fallback version. At some point in the discussions, it was suggested
> > that this function should not be pulled in except on old broken
> > systems where stdio doesn't work and needs replacement functions.
> > However, at least some packages, notably GNU M4, seem to use it
> > directly.
> 
> freadahead is one of the "extended" stdio functions that gnulib provides
> portably. "Portable" sometimes means that some porting effort is needed.

I find this a really warped definition of "portable". In a worst-case,
it's not possible to implement many of these operations at all. If for
example you had a system design where stdio was in kernelspace...

To me, portable means write once, run anywhere. I could somewhat see
extending one's definition of portable to mean "needs tuning for the
particular system, but for any given system, there's at least one way
to make it work". gnulib code is neither of these.

> It was tested using the recipe from
> http://lists.gnu.org/archive/html/bug-gnulib/2012-02/msg00022.html
> All tests pass, except for a bug in setvbuf or __fbufsize, that I have
> reported separately.
> 
> There are two areas where musl libc can be modified to reduce the size
> of this patch.
> 
> 1) Currently, gnulib has to go to a great length to detect musl.
>    It uses the presence of __stdio_read and __stdio_write as an indicator;

That's not valid. These are internal functions that could be renamed
or disappear (e.g. be changed to visibility=hidden) at any time.

I hope it doesn't sound like I'm just being pedantic here. All along,
a big part of musl's design goal has been to avoid implementation
lock-in caused by exposing internals to applications. By keeping the
interface basically just the standard C and POSIX functions, arbitrary
stable struct definitions and constants, and a moderate subset of BSD
and GNU extension functions, musl keeps its options open to replace
the internals of almost any component with an improved design, without
breaking application binaries.

When applications start probing around for internals like
__stdio_read, this goal gets a lot harder. Not only do old interfaces
that have nothing to do with a new implementation have to be preserved
(and possibly emulated); the knowledge of what interfaces are being
(ab)used by applications, and what properties applications are
depending on, is not even readily available.

>   Why does musl make it so hard?

Why does gnulib make it so hard? No other code we've encountered is
full of so many ugly system-specific hacks. The majority of packages
tested with musl _just_ _work_, or have a few minor issues like
missing includes needed to get a type defined.

>    Can't you just define a preprocessor symbol that indicates musl?
>    Like so many other systems do?

No, because the intent is NOT to support broken code like what's
currently in gnulib that hard-codes implementation-internals of
particular implementations, or worse, hard-codes assumptions that a
particular implementation is missing certain interfaces. The latter
causes serious breakage when the implementation later adds said
functionality.

Even if __MUSL__ did exist and provided you with sufficient
information to know the version, using internals specific to a
particular version would break dynamic-linked binaries used with a
different version of the library.

>    gnulib needs this because some implementations provide the same functions
>    but they behave differently. E.g. __freading is broken in glibc < 2.7
>    but not in musl. And __freading and __fwriting don't implement exactly
>    the same semantics as glibc. That's why real-life programs need to
>    #ifdef according to OS and libraries.

Then either test that __freading works, or use something like

#if defined(__GLIBC__) && __GLIBC__MAJOR__ == 2 && __GLIBC_MINOR__ < 7

to special-case the workaround only for particular known broken
versions, and otherwise assume it works. Really I prefer just making a
configure test to make sure it works...

> 2) Provide 4 primitive functions.

This is less offensive at least, but will configure even find them?
Eric Blake offered to make it work that way, but you seem to want to
test against macros that identify the implementation...? If gnulib is
willing to _detect_ working functions rather than trying to detect
musl, I'd be willing, albeit reluctant, to add them.

My favorite option would really be a #3 though: ensure that gnulib,
and gnulib-based apps, can work with a PURELY C/POSIX implementation
with no extensions and no poking at implementation internals. Then,
optionally do the ugly hacks if there's a compelling benefit, but make
sure the code doesn't break when you can't identify the system as one
you've got a set of hacks for.

Rich

Reply via email to