root-project / root

The official repository for ROOT: analyzing, storing and visualizing big data, scientifically
https://root.cern
Other
2.66k stars 1.27k forks source link

Bug in ROOT library loading - .dot sub-directories #10704

Open cholmcc opened 2 years ago

cholmcc commented 2 years ago

Bug in ROOT library loading

This small example illustrates a bug in the ROOT library loading.

I suspect that the ROOT code cannot handle directories that start with a dot (.).

Platform

The problem

To see the problem first to

$ make test 

This will generate the shared library libFoo.so.1 and associated files (libFoo_rdict.pcm, libFoo.rootmap, libFoo.so) in the sub-directory libs, and execute the script Test.C. This all works fine:

$ LD_LIBRARY_PATH=libs:<ROOTSYS>/lib root -l -b -q Test.C

Processing Test.C...
this is a Foo
hello from a Foo
rm libs/Foo_dict.o libs/Foo.o

Next, clean up

$ make clean 

so that we start afresh. Then, execute

$ make test LIBDIR=.libs 

which will build the above mentioned library and associated files in the sub-directory .libs. This fails somewhat with

$ LD_LIBRARY_PATH=.libs:<ROOTSYS>/lib -l -b -q Test.C

Processing Test.C...
Error in <TCling::RegisterModule>: Cannot open shared library <ROOTSYS>/root.exe for dictionary libFoo:
  <ROOTSYS>/root.exe: cannot dynamically load position-independent executable
Error in <TCling::LoadPCM>: ROOT PCM <ROOTSYS>/bin/libFoo_rdict.pcm file does not exist
this is a Foo
hello from a Foo

It does not matter if LIBDIR

In all cases, ROOT complains as above. If the dot is not at the start of a path component (e.g., LIBDIR=foo.libs), then all is fine.

So it seems that somewhere deep in the ROOT code, there is some assumption about a dot (.) as the leading character of a sub-directory name which shouldn't be there. As far as I can tell, the dot makes the code think that the library loaded is the ROOT executable (<ROOTSYS>/bin/root.exe) rather than the actual shared library. The reason seems to be that, because of some bad stripping of path components, the shared library isn't found by Cling and then the binary image falls back to the executable binary image.

Why this is problematic

Many build tools (e.g., Autotools) uses temporary directories that start with a dot (.), including for building examples and tests. The current behaviour of ROOT prevents building production level packages with these tools that has rigorous test suites and rich examples.

More than that, ROOT should not assume anything given a path name. Rather, it should use system tools to detect if a given path is a directory, a file, or what not. File and directory names are completely volatile and proper tools should be used to deduct what it is the code is dealing with.

Additional tests

Sub-directory with dot in name

$ make clean 
$ make test LIBDIR=foo.libs 
...
LD_LIBRARY_PATH=foo.libs:<ROOTSYS>/lib root -l -b -q Test.C

Processing Test.C...
this is a Foo
hello from a Foo

Sub-directory with leading underscore

$ make clean 
$ make test LIBDIR=_libs
...
LD_LIBRARY_PATH=_libs:<ROOTSYS>/lib root -l -b -q Test.C

Processing Test.C...
this is a Foo
hello from a Foo

Current directory

$ make clean 
$ make test LIBDIR=. 
...
LD_LIBRARY_PATH=.:<ROOTSYS>/lib root -l -b -q Test.C

Processing Test.C...
this is a Foo
hello from a Foo

root-library-load-test.tar.gz

cholmcc commented 2 years ago

Note, the full example is attached to the issue - including the report text.

ferdymercury commented 2 years ago

Maybe related: https://github.com/root-project/cling/commit/c20559d39026d67b6d9678d5c212cbf4c6a1fa02

Axel-Naumann commented 2 years ago

Thanks for your excellent report, @cholmcc - and nice to hear from you again after so many years! :-) We'll get it fixed.