Re: Discussion about why GNU/Linux system upgrades cause old programs to break

Eli Zaretskii <[email protected]> Tue, 11 Aug 2026 15:18:07 +0300
Newsgroups gmane.emacs.devel
Message-ID <[email protected]>
> From: Arsen Arsenović <[email protected]>
> Cc: Arsen Arsenović <[email protected]>,  [email protected],
>   [email protected]
> Date: Mon, 10 Aug 2026 20:50:56 +0200
> 
> Eli Zaretskii <[email protected]> writes:
> 
> >> The program didn't necessarily break in this example; the admin removed
> >> libraries that the program was linked against.
> >
> > The admin didn't remove any libraries, no.
> 
> The admin clearly did: Emacs was built and linked against a library that
> was there, and now it's not there.
> 
> Whether an upgrade did that, I do not know.

Well, I do.  Because I know when it stopped working, and what happened
immediately before that: a system upgrade.

> > What happened was a system upgrade.  I don't expect a system upgrade
> > to remove capabilities.  Am I alone in this expectation?
> 
> An upgrade can most certainly do that: if A version 1 requires B and C,
> and A version 2 requires merely B, the upgrade and and subsequent
> cleanup will remove C.

What is A in this case?  If that's Emacs, then Emacs was not upgraded,
only the OS was.  And at least in my book, upgrading should not remove
old libraries except when they are replaced with newer ones that are
ABI-compatible.  Otherwise, old programs built by users will break.

Alternatively, a program should be built in a way that it links to a
generic libFOO.so, not to a version-specific libFOO-nn.so.0, so that
upgrading will redirect the generic link to the actual library, and
programs will still work (provided that the new library is
ABI-compatible with the old one).

And if libpng12.so is just an image library and probably comes from
some add-on package, some of the libraries which broke old Emacsen are
not in that category:

  emacs-24.x/emacs-24.1/src/emacs: error while loading shared libraries: libgtk-x11-2.0.so.0: cannot open shared object file: No such file or directory

This library seems to be part of GTK and/or X11, which makes it a
"system library" in my book.

  emacs-23.x/emacs-23.1/src/emacs: error while loading shared libraries: libgpm.so.1: cannot open shared object file: No such file or directory

Same here: GPM is a system-level feature.

> This is only avoided if C was also marked as wanted (or "manually"
> installed, or added to @world, ... depending on package manager).

I don't know enough about this stuff, but if you are saying that the
sysadmin should have been more vigilant and should have paid attention
to such packages, then I submit that the defaults of the system
upgrade procedure are sub-optimal: the default should be to keep all
the installed optional features, not to remove them.  The only
exception to this rule is when a feature is incompatible with the new
OS version (which is almost certainly not the case here: libpng is
alive and kicking on latest GNU/Linux, as are GTK/X11 and GPM).

> Incidentally, I went to compile Emacs 27.2 on modern glibc and found
> that there was, in fact, a real breakage: SIGSTKSZ on GNU/Linux is not a
> constant expression anymore (seemingly because some CPUs have started
> requiring varying sizes of stacks to save register pages), if
> _DYNAMIC_STACK_SIZE_SOURCE, which is enabled with _GNU_SOURCE.

That's an example of a change in the environment which breaks
compilation of old sources.

> This happened in glibc 2.34; quoting NEWS:
> 
> > * When _DYNAMIC_STACK_SIZE_SOURCE or _GNU_SOURCE are defined,
> >   PTHREAD_STACK_MIN is no longer constant and is redefined to
> >   sysconf(_SC_THREAD_STACK_MIN).  This supports dynamic sized register
> >   sets for modern architectural features like Arm SVE.
> > 
> > * Add _SC_MINSIGSTKSZ and _SC_SIGSTKSZ.  When _DYNAMIC_STACK_SIZE_SOURCE
> >   or _GNU_SOURCE are defined, MINSIGSTKSZ and SIGSTKSZ are no longer
> >   constant on Linux.  MINSIGSTKSZ is redefined to sysconf(_SC_MINSIGSTKSZ)
> >   and SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ).  This supports
> >   dynamic sized register sets for modern architectural features like
> >   Arm SVE.
> 
> The workaround in Emacs was added in
> f97e07ea807cc6d38774a3888a15091b20645ac6.
> 
> Though, this wouldn't have broken an already-compiled Emacs.

Which is why I always keep binaries of old versions around.  But, as
the examples above show, that is not always a solution, at least on
GNU/Linux with the current system upgrade practices.

> >> If I removed libraries that my copy of Emacs 32 was linked against, it'd
> >> also "break" in the same manner, even though the Emacs 32 I have
> >> installed was built ~18 hours ago.
> >
> > Please drop the sarcasm.  This is a real problem, not a joke.
> 
> There was no sarcasm there.
> 
> That was a direct and apt analogy that explains that the specific error
> here has nothing to do with the age of the code, or indeed any factor
> related to the code itself.

Then it was a case of "reductio ad absurdum", also not useful.

> >> For instance, the example Eli gave, of programs "breaking" because GCC
> >> versions up to 14 failed to properly diagnose invalid C99, the correct
> >> interpretation is that the programs were only "working" (in air-quotes,
> >> because they cannot possibly be considered working, the same way as
> >> someone falling off a cliff is not truly flying) because GCC in
> >> particular did not enforce language rules.
> >
> > K&R syntax does not mean a program using it is broken, no.
> 
> Not necessarily, no.  A C99+ program using K&R-exclusive syntax is,
> however.

There's no such thing as a "C99+ program", not when we are talking
about a long-living program originally written long ago.  Instead, it
is the decision of the program maintainers to make it fully or
partially compatible with some C standard, which usually requires a
lot of work.

Emacs was using K&R for many years, and wasn't "broken" in any sense
of that word.

> Which is precisely what I said: "GCC [...] failed to properly diagnose
> invalid C99".

This makes no sense when we are talking about existing code.  If it
doesn't adhere to C99, then it is NOT "a C99 program"; if a compiler
decides arbitrarily to treat is as such, the build will probably
break.

IOW, it is the decision of the maintainer when and whether to need to
to diagnose invalid C99.  The compiler has no say.

> > The context here is the ability (or the lack thereof) to build a
> > program using old enough source code.
> 
> That ability was never removed, as you know.

Not removed yet.  But, having read the relevant discussions, I won't
be surprised if it will become an error (thus the build will be
broken), and if the option to make it compile without warnings will be
removed at some point.  And even if an option exists to treat these
diagnostics as warnings, seeing a deluge of warnings during a build is
not for the faint at heart, and having to dig for an option which
allows the build to complete, let alone shuts up the warnings, is also
not a very user-friendly situation.

> > We are proud in providing the source code of each of our programs,
> > indefinitely, and consider that part of the software freedom of our
> > users.
> 
> This is a point of policy, and an admirable and laudable one, that I
> wholeheartedly agree with, but...
> 
> > But in reality, try to compile an old enough source tree, and you get
> > gazillion warnings and error messages, and in some cases the problem
> > will fail to build without a lot of non-trivial tweaking (which
> > requires significant expertise).
> 
> ... this is a technical point, where Hyrum's Law manifests.
> 
> (to those who have not heard of Hyrum's Law, its statement, in brief,
> is: "for a system with enough users [for which GNU qualifies, easily],
> every observable behavior will be depended on by somebody")
> 
> There is no system in the world that manages to solve this, except by
> "simply" shipping era-appropriate copies of dependencies.

My point is that at least in some cases we decide "not to solve" this
too soon.  We could do better.  Having a program break 25 years after
it was built is much better than if it stops working after 5, I hope
you agree.

> The system vendor (be it Apple or Microsoft or Google or whoever) simply
> ships you a set of dependencies dated to, say, some year, so the
> developer ends up seeing breakages when they change which date they
> attach themselves to, because they're the ones acting as integrators for
> the vast majority of their dependencies, and their code, with the
> vendor-provided code.
> 
> The users end up not seeing this at all because each program gets
> distributed with nearly all dependencies, with the ones distributed as
> part of the OS being installed multiple times for differences in version

You are talking about programs that are part of the OS.  By contrast,
I'm talking about programs that were built by the user -- those are
not upgraded when the system is, and one of the worst effects of a
system upgrade is to see programs which worked for you for years
suddenly stop working.

> (those who have used MS-w are aware of "VC++ Redistributable XYZW" - or
> whatever the name was - which they have to install on occasion for
> various XYZW).

That's just a packaging issue: those redistributables should have been
bundled with the program that needs them, but could not be due to
copyright issues and such.  The important part is that, once you do
have the redistributable installed, no system upgrade will remove it.

> This is also why many cling to static linking.

Static linking is a two-edged sword: it could be more robust in the
long run, but in the shorter run you lose the ability to easily update
a dependency library if and when its developers fix some grave bug in
it, without the need to rebuild your application.

Most programs nowadays use dynamic linking, IME.

> > One example of this is compiling a program that used K&R syntax.
> > E.g., Emacs switched to C90-style function definitions only in version
> > 24.1, which was released in 2012.  All the older versions used K&R
> > syntax; they are now "broken" by your definitions, and cannot be
> > easily compiled.
> 
> Well, yes, if Emacs versions up to 2012 were telling the compiler that
> they were C99 programs, but were not valid C99, they were certainly
> broken, and only worked due to a defect in GCC.

See above: that's not what happens.  In reality, the build invokes the
compiler without specifying the dialect, so whatever is the default C
dialect is being used.  So when the default changes to be
backward-incompatible, it's bound to break old programs.

> Indeed, GCC should've been diagnosing those constructs back in 2012.  Or
> 2000.  Then, this situation would not have happened.

Emacs was written in 1986, as you know.  So 2000 would still be too
late.

> In name of backwards compatibility, we've made many more incorrect
> programs to be "compatible" with.

You make it sound like a sin, but I happen to think it's a virtue.
Backward compatibility is an important aspect of being user friendly
in my book.

> I've argued before, and stand by it now, that source-level backwards
> compatibility should not be the default for compiled languages.  When a
> compiler is present, it should only be backwards-compatible if told to
> be explicitly.

This makes recompiling old sources harder, so I think it's a mistake,
unless we don't care about these case.

> That's, obviously, not to say that we should break things willy-nilly,
> but the removal of certain K&R syntax from C99 was a considered move
> done long ago.

I always thought that in the GNU project we don't blindly follow The
Powers That Be out there when they decide to remove or EOL something.
Instead, we make our own decisions, based, in no small measure, the
benefits and disadvantages for our users.