8 ms·
The glibc s390 ABI break (2014)
- AnssiH 5y agoFWIW, this ABI break was reverted 2 weeks after the LWN article was released: commit 2f438e20ab591641760e97458d5d1569942eced5 Author: Stefan Liebler <___.ibm.com> Date: Thu Jul 31 20:04:54 2014 +0200 S/390: Revert the jmp_buf/ucontext_t ABI change.
- jancsika 5y ago> libc.so.6.1 My brain hurts-- if libc.so.6.1 is a nightmare, then what is the utility of having the libc.so.6 soname numbering at all? I'll put it in a more effective wrong-thing-on-the-internet style for receiving responses: There's no point in using NixOS. Just use lib.so.versionNumber. (Sorry) :)
- deleted 5y ago[deleted]
- jcranmer 5y agoThe problem with sonames for libc is that libc is too foundational of a library to really have multiple incompatible versions running around [1]. There is no way for an application to have multiple versions of libc in its memory space. When you live in a modern world where applications will pull in multiple third-party packages that all depend on core packages, those core packages better be extremely good about backwards compatibility or there is immense pain on adopting new versions (see also Python 2->3 transition). [1] Or, perhaps more accurately, an incompatible version of libc requires the creation of an entire distinct target triple. You can have multiple incompatible versions if you've got a multiarch setup of some kind (like 32-bit and 64-bit x86 code on the same system), but an application can't simultaneously use both in the same process in such systems still.
- Arnavion 5y agoIt's partly a Linux-specific problem. Windows programs are fine with having multiple copies of MSVCRT loaded into the same process. It's often unavoidable; any process that loads plugin libraries will have its own CRT plus other CRTs pulled in by the plugins in its address space. Just open up some process in procexp and see how many msvcrt##.dll you find loaded. It means every library has to be careful about providing both malloc and free calls in their API. Eg if a library has a `Foo *create_foo(void)` it has to provide a `void delete_foo(Foo*)`, instead of expecting the user to call `free(the_foo)` because that `free` might be from the wrong CRT. With Linux libraries I often find that you have a `create_foo` but no `delete_foo`, and you're expected to just `free` it. I assume Linux libraries never took this much care historically because software was generally open-source, so everyone was getting their software from distro repos that rebuilt the world to link to a single libc.
- yjftsjthsd-h 5y agoYou should know that HN lets you prefix stars with a backslash to escape them, so your text ends up saying, ex. foo*bar and bar*baz rather than foobar and barbaz
- Arnavion 5y agoI know. I fixed it shortly after I posted the comment.
- jcranmer 5y agoglibc serves multiple purposes, and these purposes are broken up into separate libraries on Windows. One of those purposes is to act as the C standard library, which is what is provided by msvcrt.dll. But another purpose is to act as the library of system services, which is provided by kernel32.dll instead. The actual functionality that glibc broke in this specific ABI break is really the sort of functionality that is provided by kernel32.dll (i.e.., that's where the SEH functions live) on Windows. And you can't provide multiple copies of kernel32.dll on Windows, just like you can't have multiple copies of glibc.
- 5y ago
- jancsika 5y agoIn keeping with my confidently-wrong-on-the-internet theme: Nobody is trying to run multiple incompatible versions of glibc in a single application. The point is to run multiple different versions of the same application on a single OS, where each version uses a different version of glibc. NixOS is wildly over-engineered for this purpose. Just use lib.so.versionNumber, full stop. And, scene. :)
- assbuttbuttass 5y agoIf some library e.g. libpng depends on a particular version of glibc, and your application depends on libpng and glibc, you better hope they want the same version
- jancsika 5y agoI'm still not getting it. Doesn't libpng use the soname.someVersion, too?
- assbuttbuttass 5y agoWell suppose to libpng depends on glibc version 6.0, but when you try to link your app it will find the latest glibc 6.1. Only one of these versions is going to get loaded at runtime. The compiler's not going to check compatibility between all the different libraries.
- jancsika 5y agoIf the highest number always gets chosen then what's the point of libname.so.versionNumber in the first place?
- rlpb 5y agoThe point is for runtime. At build time generally the latest available version is used (via a symlink) and then that version gets locked in to the resulting binary.
- rwmj 5y agoI remember using Linux with libc.so.4 & .5 (which were not based on glibc code). libc 4 used a pre-ELF scheme called a.out, and libc 5 used ELF. When Linux distros started to adopt GNU libc 2.x, the soname was 6 (to be obviously higher than previous versions) and they promised the new ELF symbol versioning scheme which meant that the version number would never have to change again. So here we are.
- marcodiego 5y agoI've been using linux since late 90's and the only related thing I remember was to have to install an "old" libc to be able to run kylix. Do you have more info on this event? Seems to have completely vanished from my memory.
- rwmj 5y agoI guess you may not remember the a.out to ELF transition, which was a "Big Bang" event. Before ELF, shared libraries did not use position independent code and so load addresses had to be globally coordinated (with extra space left for a library to grow in size!). That was libc.so.4 (old libc, a.out) -> libc.so.5 (old libc, ELF) and Linux 1.2. I don't recall if there were libc < 4. Google says this happened in around 1995. The libc.so.5 (old libc, ELF) to libc.so.6 (glibc 2.0) transition happened a little later in 1997.
- marcodiego 5y agoI remember the a.out to elf transition because the first distro I used had Doom in its repos. When I installed it complained that a.out format wasn't supported anymore. IIRC I tried kylix in 1999. It still requiring libc5 is strange. Well... those were not best inprise/borland days indeed.
- yjftsjthsd-h 5y ago> I remember using Linux with libc.so.4 & .5 (which were not based on glibc code). What libc implementation was that, then? I thought glibc was the first to support Linux.
- deleted 5y ago[deleted]
- somat 5y agoI always feel the Linux people learn the wrong lesson from these events. The difference between the Linux and the OpenBSD mentality in one example. The ABI must be changed. Linux: That was really hard, we are never going to do that again. OpenBSD: That was really hard, we better get good at it. My opinion: When your deliverable is made up of source code(like these open source projects are), the ABI and ABI stability is not that important, it is the API(the source interface) that is critical.
- leeter 5y agoThis forgets MS: MS: "Let's design it so either it never breaks or if we can't avoid that we'll just add a FooEx or Foo2 method call" This is why so many Win32 methods take structs that have a size parameter that must be filled in. That acts as a version parameter. That's not to say they haven't had ABI fun moments... glares at COM.
- secondcoming 5y agoOne flaw with that is that the struct size won't change if you do something like reordering the members (not that anyone would ever do that).
- leeter 5y agoWhich they explicitly prohibit, in fact if you look at how they design the APIs they'll deliberately add reserved members to ensure they hold the space so that it's much harder to break.
- asveikau 5y agoYes, it takes some discipline to keep that working. You need to internalize which changes cause ABI breaks, look for them in code reviews, evangelize that culture to new hires that aren't familiar with the rules (which becomes harder over time as people coming up now tend to spend less time learning C), etc.
- Someone 5y agoExample: https://gankra.github.io/blah/c-isnt-a-language/#case-study-minidump_handle_data https://gankra.github.io/blah/c-isnt-a-language/#case-study-...
- schemescape 5y ago> Debian's developers ... considered rebuilding all of Perl and then, perhaps, all (500 or so) packages depending on the PNG library libpng using setjmp.h for error handling was always my least favorite part of libpng, especially since the libpng documentation indicates it was just done for convenience (tell that to the authors of the OP!): > The motivation behind using setjmp() and longjmp() is the C++ throw and catch exception handling methods. This makes the code much easier to write, as there is no need to check every return code of every function call.
- kragen 5y agoIt's not just convenience for the authors of libpng; it's also convenience for libpng's users, because it means they can handle errors at a single location instead of checking the return code of every function call. It is true that changing the size of jmp_buf breaks binary compatibility, but that's hardly a unique fatal flaw in setjmp/longjmp; it's also true of fd_set, struct timeval, struct tm, struct sockaddr, struct stat, and all the other exposed memory-layout interfaces mentioned in the article: __pthread_unwind_buf_t, PerlInterpreter, png_struct_def, etc. Indeed, you'd think it would be much less of a problem for jmp_buf, because normally the things stored in a jmp_buf are precisely the callee-saved registers in your ABI; changing that involves comprehensively breaking your ABI anyway. There is a big advantage in C to exposing the memory layout of a struct in this way: it doesn't need to be heap-allocated, so it doesn't introduce a dependency on heap allocation (which wasn't part of the standard library at all when setjmp was defined, and is still forbidden in many contexts), and you can statically bound your program's memory use, so you can be sure it won't fail. Heap allocation can always fail, so you can only ever use it in programs where failure is an option. You don't want your antilock braking system to raise an exception and reboot because its heap has become fragmented.
- mrlonglong 5y agoI felt the pain transitioning from libc5 to glibc 2 a long long time ago. Glad I never had to do that again.
- anyfoo 5y agoHah, I remember that. The pain was acceptable in my case since I was still at school and did this purely for "fun" because I wanted to. Both this move to glibc and the prior move from a.out to ELF taught me an incredible amount about Linux (and unixoid systems in general) because I had to rebuild pretty much everything in the system by hand, reading everything's READMEs and learning a bit more about them. (My system at the time originally came from a distribution installed by CD, but was then never upgraded the official way but only move forward with source tarballs, i.e. no package management. I got that luxury much later.) Fun times.
- mrlonglong 5y agoFor a few years I built my system using sources leached off freshmeat.net. Discovered Gentoo and never looked back since. Although they do cock up once in a while, they can be forgiven since they're entirely volunteer run.