[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Is the Debian dependency system broken? (wget vs libgnutls-deb0-28)

Vincent Lefevre <vincent@vinc17.net> writes:
> On 2015-06-16 09:12:36 -0700, Russ Allbery wrote:

>> There are a lot of really complex things you can do with versioning and
>> cases where that version number is meaningful, but for the vast
>> majority of libraries, I recommend not worrying about it and just
>> always using some simple transform of the SONAME as the version for all
>> symbols in the library.  When you bump the SONAME, bump all the symbol
>> versions.  When you introduce a new symbol, use the SONAME as the
>> symbol version.

>> This is not strictly correct in that the symbol version doesn't
>> correspond to a specific API (you're adding new symbols with the same
>> symbol version as old symbols), but most of the functionality you lose
>> is just meaningful error messages when running new binaries against
>> too-old versions of the shared library.  And it's way simpler to
>> implement.

> But can this be detected so that a versioned dependency of the shared
> library can *automatically* be added when the binary packages are
> generated, avoiding this problem?

I'm not sure what "this" you're referring to.

If you mean detecting that you have newer binaries that require a new
version of the shared library, and thus the shared library needs to be
upgraded, yes, absolutely.  Debian solved this problem years and years
ago.  That's what you're fixing by bumping the version in dh_makeshlibs in
the shared library package: signaling that binary packages should have a
tigher versioned dependency.  debian/symbols does this in an even more
sophisticated way.

Just in case, by "this", you meant the whole problem of shared library
upgrades where you *don't* have symbol versions, here's the long-winded
explanation for why you need symbol versions and package dependencies
don't cut it:

It is nearly impossible to solve this problem with package dependencies.
Shared library symbol versioning is required to solve the problem
properly and without painstaking and very fragile manual work.

This is because the problem is not with direct dependencies on a shared
library, but rather with indirect dependencies.  What happens is that you
have some library -- call it liblow1 -- and you have two other libraries
that use it -- call them libfoo1 and libbar1.  liblow1 does not have
symbol versioning.  An incompatible liblow2 is released.  The user
upgrades the system such that libfoo1 is rebuilt against liblow2, but
libbar1 is not.

Now, some application, app, which is linked against both libfoo1 and
libbar1, is started.  What happens is that calls to the functions in
liblow1 and liblow2 go to one of the two implementations semi-randomly,
and one of either libfoo1 or libbar1 is going to break horribly, usually
in some very subtle and awful way.

There are a bunch of ELF tricks that you can try to do to minimize this,
but none of them are 100% effective.  However, symbol versioning is 100%
effective, since then libfoo1 and libbar1 are linked against specific
versioned symbols, there are no symbol conflicts between liblow1 and
liblow2, and both get loaded into memory, both are used appropriately, and
app works.

To try to solve this with dependencies, you have to make liblow2 conflict
with liblow1.  But this completely breaks shared library upgrades, since
now you have to upgrade every program linked to liblow in lockstep, even
if there's no risk for that application of loading two versions at the
same time, because you can't have both shared libraries on the system at
the same time.  It also wipes out our dependency resolver, because there
are too many conflicts to find a good solution.

Alternately, you can do what we're trying to do here, which is add a
complex mess of Breaks and Conflicts to all the various consumers of
liblow1 and hope that you caught them all.  Spoiler: you never catch them
all.  Particularly since some of them are user programs that aren't even
part of the distribution.

Shared library symbol versioning makes the problem go away.  Package
dependencies try to solve the problem at the wrong level.

Russ Allbery (rra@debian.org)               <http://www.eyrie.org/~eagle/>

Reply to: