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