develooper Front page | perl.perl5.porters | Postings from June 2003

Problems: 5.8.1, Solaris, Configure, sched_yield(), -lrt & -lposix4

Thread Next
From:
Alan Burlison
Date:
June 25, 2003 17:19
Subject:
Problems: 5.8.1, Solaris, Configure, sched_yield(), -lrt & -lposix4
Message ID:
3EFA3BFB.3B030A15@sun.com
I was poking at a non-threaded build of 5.8.1-to-be, and I noticed this:

$ LD_LIBRARY_PATH=. ldd perl
        libperl.so =>    ./libperl.so
        libsocket.so.1 =>        /lib/libsocket.so.1
        libnsl.so.1 =>   /lib/libnsl.so.1
        libdl.so.1 =>    /lib/libdl.so.1
        libm.so.1 =>     /usr/lib/libm.so.1
        libc.so.1 =>     /lib/libc.so.1
        librt.so.1 =>    /lib/librt.so.1
        libmp.so.2 =>    /lib/libmp.so.2
        libaio.so.1 =>   /lib/libaio.so.1
        libmd5.so.1 =>   /lib/libmd5.so.1
        /platform/SUNW,Ultra-5_10/lib/libc_psr.so.1
        /platform/SUNW,Ultra-5_10/lib/libmd5_psr.so.1

which caused me to wonder by perl was linking against librt, libmp and
libaio by default, and uncovered a whole load of other issues with
regard to the way perl is linked.

The first issue, the inclusion of -lrt and -lposix4 has happened because
Configure has been changed at some point between 5.6.1 and 5.8.1:

[5.6.1 Configure]
libswanted="$libswanted ucb bsd BSD PW x iconv util"

[5.8.1 Configure]
libswanted="$libswanted ucb bsd BSD PW x util rt posix4"

Why have librt and posix4 been added to libswanted in Configure?  On
Solaris at least they don't provide any symbols that are required for a
non-threaded perl, as far as I can tell the only reason -lrt is needed
even in threaded perl is for the sched_yield() function.  Also the
Solaris manpage for libposix4 says:

     The name libposix4 is maintained for backward  compatibility
     and  should be avoided. librt is the preferred name for this
     library.

so -lposix4 isn't needed either.  If these libraries *are* required,
they should a) be done by the platform-specific hints file and b) only
be added when they are required, i.e. when building threaded.

There is however another slightly more serious issue related to librt
and it's dependent libaio.  On Solaris libaio provides replacements for
some standard libc functions to modify their behaviour, most
specifically for fork().  This replaces the standard 'fork all threads'
semantics of fork with one that only forks the calling thread.  However
in order for this to work, librt (and therefore libaio) have to be
mentioned in the link line *before* libc, and this isn't the case:

[config.sh]
libs='-lsocket -lnsl -ldl -lm -lc -lrt -lposix4'

Although in this instance the issue is related to -lrt/-laio, it is a
generic issue - libraries sometimes need to override symbols in libc,
and therefore need to be searched *before* libc, and therefore normally
need to come *before* libc on the link line.  In fact it is usually a
bad idea to mention -lc on the link line anyway if you are using 'cc' as
the linker.  I suggest therefore that -lc either be removed entirely, or
alternatively that we ensure it is always last on the link line.

The other observation is that it isn't actually necessary to link
against librt in the first place on Solaris then building threaded.  As
far as I can see, the only reason for linking against librt is to get
access to sched_yield, but sched_yield (and indeed thr_yield) are just
aliases for the yield(2) system call.  I therefore suggest that on
Solaris we should use yield(2).  However having looked at the tangled
web in Configure and thread.h I'm not sure of the best way of doing
this, a Configure probe or some macro magic in thread.h - anyone have
any suggestions?

The final point of note is that perl is linked against libraries that it
doesn't actually use:

cc -o perl   -R /usr/perl5/5.8.1/lib/sun4-solaris-64int/CORE perlmain.o
lib/auto/DynaLoader/DynaLoader.a  libperl.so `cat ext.libs` -lsocket
-lnsl -ldl -lm -lc -lrt -lposix4
debug: 
debug: 
debug: 
debug: file=libsocket.so.1  unused: does not satisfy any references
debug: file=libnsl.so.1  unused: does not satisfy any references
debug: file=libm.so.1  unused: does not satisfy any references
debug: file=librt.so.1  unused: does not satisfy any references
debug: 
debug: 

and that by default libperl doesn't have *any* linker dependencies at
all, which seems broken.  If I hack Makefile to add the contents of
$libs to the link line, we can see that there is still some unused cruft
in there:

cc -o libperl.so -G perl.o  gv.o toke.o perly.o op.o pad.o regcomp.o
dump.o util.o mg.o reentr.o hv.o av.o run.o pp_hot.o sv.o pp.o scope.o
pp_ctl.o pp_sys.o doop.o doio.o regexec.o utf8.o taint.o deb.o
universal.o xsutils.o globals.o perlio.o perlapi.o numeric.o locale.o
pp_pack.o pp_sort.o  -lsocket -lnsl -ldl -lm -lc -lrt -lposix4
debug: 
debug: 
debug: 
debug: file=libdl.so.1  unused: does not satisfy any references
debug: file=librt.so.1  unused: does not satisfy any references
debug: 
debug: 

however, if we get rid of the rt and posix4 that have crept into
Configure, that problem will disappear.  Another trick we can pull on
Solaris is to add '-z ignore' to the link line, which will ignore
libraries that don't contain referenced symbols, and '-z lazyload' which
will defer symbol resolution until a symbol is accessed.  My testing
shows that this speeds up 'perl -e exit' by about 18%, which seems worth
having.  These linker flags aren't available on all Solaris releases, so
a probe in the solaris2.sh will be required.

So to summarise:

1. Configure should not include rt or posix4 in libswanted.
2. -lc should be removed/moved to the end of the link line.
3. On Solaris we should use yield() when threaded (how best to do
this?).
4. $libs should be added to the libperl.so link line in Makefile.
5. -z ignore and -z lazyload should be probed for in the hints file, and
used if available.

Unless anyone can suggest a good reason why not, I will submit a patch
to clean all this up.

Alan Burlison

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About