libtool-patches
[Top][All Lists]
Advanced

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

Re: lt_dlerror changes


From: Charles Wilson
Subject: Re: lt_dlerror changes
Date: Fri, 18 Jun 2010 10:50:30 -0400
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.23) Gecko/20090812 Thunderbird/2.0.0.23 Mnenhy/0.7.6.666

On 6/18/2010 9:36 AM, Peter O'Gorman wrote:
> On 06/18/2010 08:33 AM, Peter O'Gorman wrote:
>> Yes, the preopen loader gets tried first with last.a, it failed, then
>> find_handle is called which does an access() check for last in every dir
>> in path,
> 
> Correction for lack of coffee: not "PATH", but LTDL_LIBRARY_PATH,
> LD_LIBRARY_PATH (or whatever) and the standard library paths.

Nope, I'm debugging right now, and I'm looking at

#0  foreach_dirinpath (search_path=0x10d8b5d
"/usr/local/bin:/usr/bin:/usr/bin:/tex/miktex/bin:/c/program
files/graphicsmagick-1.1.11-q8:/c/windows/system32:/c/windows:/c/windows/system32/wbem:/c/program
files/cyberlink/power2go/:/c/Program Files"..., base_name=0x10e9ec0
"last", func=0x405040 <find_handle_callback>, data1=0x22cc30, data2=0x0)
at ../libtool/libltdl/ltdl.c:681
#1  0x0040448c in find_handle (phandle=0x22cc78, filename=<value
optimized out>, ext=0x10e9ec4 "", advise=0x0) at
../libtool/libltdl/ltdl.c:806
#2  try_dlopen (phandle=0x22cc78, filename=<value optimized out>,
ext=0x10e9ec4 "", advise=0x0) at ../libtool/libltdl/ltdl.c:1466
#3  0x00404e4e in lt_dlopenadvise (filename=0x408244 "last", advise=0x0)
at ../libtool/libltdl/ltdl.c:1674
#4  0x00405039 in lt_dlopen (filename=0x408244 "last") at
../libtool/libltdl/ltdl.c:1628
#5  0x004014a2 in main (argc=<value optimized out>, argv=<value
optimized out>) at main.c:288


That is, search_path = $PATH.  This is because (ltdl.c:try_dlopen):

1466  if ((dir || (!find_handle (user_search_path, base_name,
1467                             &newhandle, advise)
1468      && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name
1469                       &newhandle, advise)
1470 #if defined(LT_MODULE_PATH_VAR)
1471      && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
1472                       &newhandle, advise)
1473 #endif
1474 #if defined(LT_DLSEARCH_PATH)
1475      && !find_handle (sys_dlsearch_path, base_name,
1476                       &newhandle, advise)
1477 #endif
1478     )))

where

config.h:#define LT_MODULE_PATH_VAR "PATH"
config.h:#define LT_DLSEARCH_PATH "/lib:/usr/lib"
(and the env var $LTDL_LIBRARY_PATH is not set)

So, of the four calls to find_handle above, I'm in the third one. While
iterating thru $PATH, of course ONE of the possibilities is
"/usr/bin/last".  Most of the loaders fail:
   first
   preopen
   dlopen
   loadlibrary
although oddly, loadlibrary sets CANNOT_OPEN instead of FILE_NOT_FOUND
(loadlibary.c:vmopen):

232         if (!module)
233           LOADLIB_SETERROR (CANNOT_OPEN);
234         else if (cur)
235           {
236             LT__SETERROR (CANNOT_OPEN);
237             module = 0;
238           }

I think there should be an earlier check for !module @ 206, and THAT one
should set FILE_NOT_FOUND.  However, this isn't the cause of the current
problem.

But in any case, it appears the problem is (ltdl.c):

778     static int
779     find_handle_callback (char *filename, void *data, void *data2)
780     {
781       lt_dlhandle  *phandle         = (lt_dlhandle *) data;
782       int           notfound        = access (filename, R_OK);
783       lt_dladvise   advise          = (lt_dladvise) data2;
784     
785       /* Bail out if file cannot be read...  */
786       if (notfound)
787         return 0;

when called with '/usr/bin/last', cygwin's access returns 0, because of
the .exe magic.

However, the real issue isn't the exe magic, it's the fact that the test
makes assumptions about what files ARE or ARE NOT in the
LT_MODULE_PATH_VAR.  We *hope* that there is no "last" or "first" or
"module" or "no_module" anywhere in there.

Because of the design decision in find_handle_callback:

 789   /* Try to dlopen the file, but do not continue searching in any
 790      case.  */
 791   if (tryall_dlopen (phandle, filename, advise, 0) != 0)
 792     *phandle = 0;
 793
 794   return 1;
 795 }

If we EVER find a file anywhere in LT_MODULE_PATH_VAR that "exists" and
matches the desired (base)name, but cannot open it, then we never search
any more in the path (see foreach_dirinpath) -- NOR do we ever just try
to open the name without any path prefixed to it.  That is, we never hit
line 1480 in ltdl.c:try_dlopen:


1480      if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1481        {
1482          newhandle = NULL;
1483        }

which WOULD HAVE succeeded using the 'last' loader.  So the test fails
simply because "/usr/bin/last.exe" exists, causing access
("/usr/bin/last", ...) to return 0 rather than -1.

NOTE that it makes no difference whether the loader is "first" in the
chain or "last": I created /usr/bin/first.exe (since our test of the
'first' loader tries to load a module named 'first') and I got the same
error, only this time (a) much earlier in main(), and (b) with
/usr/bin/first.  All loaders will encounter the code around
ltdl.c(try_dlopen):1466, with the behavior below:

I guess the real question is, why is

   tryall_dlopen (..., attempt, ...)

the last resort when attempt is a bare name, after each of

  find_handle (user_search_path, base_name, ...
  find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, ...
  find_handle (getenv (LT_MODULE_PATH_VAR), base_name, ...
  find_handle (sys_dlsearch_path, base_name, ...

fail -- *especially* with custom loaders?

However, if this IS the desired algorithm, then the "fix" is for our
test to putenv (LT_MODULE_PATH_VAR, ""), right? And probably
LTDL_SEARCHPATH_VAR, as well. But I'm not sure we can guarantee to "null
out" sys_dlsearch_path at runtime; what if a file called "/usr/lib/last"
exists, even on linux?

--
Chuck



reply via email to

[Prev in Thread] Current Thread [Next in Thread]