the sorry saga of the talloc soname 'fix'

Stefan (metze) Metzmacher metze at samba.org
Wed Jul 8 16:03:58 GMT 2009


Hi Tridge,

> So to me it should not go in the core code. If you think it needs to
> be in a common place so that deb and RPM based distros coordinate,
> then put it in a packaging/ subdirectory.
> 
> In all of this please also remember just how much of the Samba
> codebase is now in shared libs. The librpc code alone is over 500k
> lines of code, including the generated code. That lib is used by
> external projects, and may be called both directly and indirectly by
> apps, just like talloc is.

But librpc doesn't have a stable marked API yet.

> Whatever method we establish for handling shared libs now is not just
> for talloc. It applies to a very large proportion of the projects code
> base. I do not want that entire code base constrained by external
> shared lib concerns. I do not want the maintenance of the shared lib
> ABI to become the responsibility of every contributor to Samba. 

I think talloc, tdb (and later tevent and ldb) are special
and we should treat them more as standalone libraries with a fixed API.
And there standalone build systems are independent from samba4.

The samba4 rpc and smb client libraries are really not stable yet,
but that's know to the callers openchange always needs to be build
against a fixed snapshot.

BTW: the problem with static and shared linking together is a completely
different thing and should be ignored in this discussion.

As I said before I've done some testing with compat libraries.
I created some very simple examples, which show how two versions of a
(liba.so.1 and liba.so.2) can be coexists within one process.

The trick is that the liba.so.1 compat library is build on top
of the public API of liba.so.2 and also links to it. That means the
compat library only provides symbols which are not in the new library
and it also do not know about private data of liba.so.2.

I tried some combinations which can happen:

libb.so.1 was build against liba.so.1 and is happy with the old
liba.so.1, but also with the compat version of liba.so.1 at runtime.

appa1 was build against liba.so.1 and is happy with the old liba.so.1,
but also with the compat version of liba.so.1 at runtime.

appa2 was build against liba.so.2 and is only happy with liba.so.2.

appa2b1 was build against liba.so.2 and libb.so.1 and is happy when at
runtime the compat version of liba.so.1 is implicit loaded via libb.so.1.

I think such a compat library could be an alternative to symbol
versioning and could be located in lib/talloc/compat/.

metze

The output of the runme.sh follows:

# make -C liba1 clean
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/liba1'
rm -f *.o *.so*
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/liba1'
# make -C liba1
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/liba1'
ccache gcc -fPIC   -c -o liba.o liba.c
gcc -shared -o liba.so.1 -Wl,-soname=liba.so.1 liba.o
rm -f liba.so
ln -s liba.so.1 liba.so
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/liba1'
# make -C liba2 clean
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/liba2'
rm -f *.o *.so*
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/liba2'
# make -C liba2
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/liba2'
ccache gcc -fPIC   -c -o liba.o liba.c
gcc -shared -o liba.so.2 -Wl,-soname=liba.so.2 liba.o
rm -f liba.so
ln -s liba.so.2 liba.so
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/liba2'
# make -C liba2-compat1 clean
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/liba2-compat1'
rm -f *.o *.so*
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/liba2-compat1'
# make -C liba2-compat1
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/liba2-compat1'
ccache gcc -fPIC   -c -o liba2-compat1.o liba2-compat1.c
gcc -shared -o liba2-compat1.so -Wl,-soname=liba.so.1 liba2-compat1.o
../liba2/liba.so
rm -f liba.so.1
ln -s liba2-compat1.so liba.so.1
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/liba2-compat1'
# make -C libb1 clean
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/libb1'
rm -f *.o *.so*
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/libb1'
# make -C libb1
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/libb1'
ccache gcc -fPIC   -c -o libb.o libb.c
gcc -shared -o libb.so.1 -Wl,-soname=libb.so.1 libb.o ../liba1/liba.so
rm -f libb.so
ln -s libb.so.1 libb.so
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/libb1'
# make -C appa1 clean
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/appa1'
rm -f *.o *.so* appa1
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/appa1'
# make -C appa1
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/appa1'
ccache gcc    -c -o app.o app.c
gcc -o appa1 app.o ../liba1/liba.so
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/appa1'
# make -C appa2 clean
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/appa2'
rm -f *.o *.so* appa2
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/appa2'
# make -C appa2
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/appa2'
ccache gcc    -c -o app.o app.c
gcc -o appa2 app.o ../liba2/liba.so
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/appa2'
# make -C appa2b1 clean
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/appa2b1'
rm -f *.o *.so* appa2b1
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/appa2b1'
# make -C appa2b1
make: Gehe in Verzeichnis '/tmp/junkcode/shared-libs/appa2b1'
ccache gcc    -c -o app.o app.c
gcc -o appa2b1 app.o ../liba2/liba.so ../libb1/libb.so
-Wl,-rpath-link,../liba1/
/usr/bin/ld: warning: liba.so.1, needed by ../libb1/libb.so, may
conflict with liba.so.2
make: Verlasse Verzeichnis '/tmp/junkcode/shared-libs/appa2b1'

# LD_LIBRARY_PATH=liba1 appa1/appa1
appa1: ...
liba1: libafunc1(1) = 0
appa1: ... 0

# LD_LIBRARY_PATH=liba1 ldd appa1/appa1
	linux-vdso.so.1 =>  (0x00007fff71ffe000)
	liba.so.1 => liba1/liba.so.1 (0x00007f2669ab8000)
	libc.so.6 => /lib/libc.so.6 (0x00007f2669756000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2669cb9000)

# LD_LIBRARY_PATH=liba1 appa1/appa1
appa1: ...
liba1: libafunc1(1) = 0
appa1: ... 0

# LD_LIBRARY_PATH=liba2-compat1:liba2 ldd appa1/appa1
	linux-vdso.so.1 =>  (0x00007fff4d9fe000)
	liba.so.1 => liba2-compat1/liba.so.1 (0x00007f8a454a4000)
	libc.so.6 => /lib/libc.so.6 (0x00007f8a45142000)
	liba.so.2 => liba2/liba.so.2 (0x00007f8a44f41000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f8a456a5000)

# LD_LIBRARY_PATH=liba2-compat1:liba2 appa1/appa1
appa1: ...
liba2-compat1: libafunc1(1) ...
liba2: _libafunc1(1, liba2-compat1-location) = -1
liba2-compat1: ... -1 => 0
appa1: ... 0

# LD_LIBRARY_PATH=liba2 ldd appa2/appa2
	linux-vdso.so.1 =>  (0x00007fff009fe000)
	liba.so.2 => liba2/liba.so.2 (0x00007f09f8570000)
	libc.so.6 => /lib/libc.so.6 (0x00007f09f820e000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f09f8771000)

# LD_LIBRARY_PATH=liba2 appa2/appa2
appa2: ...
liba2: _libafunc1(2, app.c:10) = -1
appa2: ... -1
appa2: ...
liba2: libafunc2(2) = 0
appa2: ... 0

# LD_LIBRARY_PATH=liba2:libb1:liba2-compat1 ldd appa2b1/appa2b1
	linux-vdso.so.1 =>  (0x00007fff725fe000)
	liba.so.2 => liba2/liba.so.2 (0x00007fa46a096000)
	libb.so.1 => libb1/libb.so.1 (0x00007fa469e95000)
	libc.so.6 => /lib/libc.so.6 (0x00007fa469b33000)
	liba.so.1 => liba2-compat1/liba.so.1 (0x00007fa469932000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa46a297000)

# LD_LIBRARY_PATH=liba2:libb1:liba2-compat1 appa2b1/appa2b1
appa2: ...
liba2: _libafunc1(21, app.c:11) = -1
appa2: ... -1
appa2: ...
liba2: libafunc2(21) = 0
appa2: ... 0
appa2: ...
libb1: libbfunc1(21) ...
liba2-compat1: libafunc1(21) ...
liba2: _libafunc1(21, liba2-compat1-location) = -1
liba2-compat1: ... -1 => 0
libb1: ... 0
appa2: ... 0


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 252 bytes
Desc: OpenPGP digital signature
Url : http://lists.samba.org/archive/samba-technical/attachments/20090708/7c3657a4/signature.bin


More information about the samba-technical mailing list