Hi Peter, On 10 Jun 2010, at 12:33, Peter O'Gorman wrote: > As I am sure many are aware, libltdl's error reporting is pretty dumb, > lt_dlerror() regularly reports things like "file not found" where the actual > problem might be something completely different, and a reasonable error > string may be readily available from dlerror().
Treason! > When I looked at the manual, and read the description for lt_dlerror() I saw > "Return a human readable string describing the most recent error that > occurred from any of libltdl's functions. Return NULL if no errors have > occurred since initialization or since it was last called." and I thought > "Well, that's stupid - that's not what dlerror() does". So, I went to see > what POSIX says - it's also wrong - > http://www.opengroup.org/onlinepubs/9699919799/functions/dlerror.html, I will > file a bug with them later. > > At least glibc and Mac OS X reset the dlerror() string to NULL every time a > dl*() api is called (I will check what other systems do in the next few > days). This is so programmers can do: > > ..... > dlsym(handle, "foo"); > if ((err = dlerror()) != NULL) printf(stderr,"dlsym error: %s\n",err); > ... > > without dlerror() returning some other error that occurred long before the > call to dlsym(). Interesting. IIRC, Thomas chose the semantics and API of libltdl to closely match the Unix dlfcn.h calls so that it could be used as a direct replacement by a client with very little editing. If glibc and OS X (which to my mind probably covers 80% of the users of libltdl) is already doing something saner than the documentation might have lead us to believe, then your change looks like a net win to me! Aside: I'm leaning away from upholding the 'drop-in-with-minimum-edits' philosophy for my rewrite, since the dlfcn.h API seems like a pretty bad design to me. After all, all people really need to do is call functions with a known name and known signature which happen to be in another library. I'm seriously contemplating using a *much* smaller and cleaner API, which ends up with client code more along the lines of: #include <setjmp.h> static jmp_buf exception; void * my_get_dso_func (const char *dsopath, const char *symname) { if (! setjmp (exception)) { /* setjmp returns 0 on first invocation */ return lt_dlsym (dsopath, symname); } else { /* but if lt_dlsym throws an exception, we end up here */ fputs ("myapp: my_get_dso_func failed", stderr); } } With that as a starting point, it's easy enough to maintain an error stack in an exception struct that wraps around setjmp/longjmp, and to pretty up the code above with some macros to make it look more like the common throw/catch syntax. At that point, with libltdl2 doing the book-keeping, the entire API is just: typedef void *lt_exception; void *lt_dlsym (const char *dsopath, const char *symname); void lt_dlclose (const char *dsopath); plus some glue to make catching an error thrown from libltdl2 and for unwinding the error stack inside it as easy as possible. WDYT? > Unfortunately, it looks like libltdl attempts to save error state across > calls to lt_*() functions, and generally does not do it well. > > This patch resets the error every time a public ltdl function is called, and > when setting an error tests if it is already set and doesn't overwrite it if > it is. The fist error "wins". > > The patch is fairly simple, and undoubtedly still imperfect, but test results > are good, one test required a small patch to stop segfaulting, another should > have unexpectedly passed, but doesn't, I think it is another error in the > test, but haven't looked too closely yet. > > If something like this does get in, I'd prefer to not change the libltld > soname, I don't believe better error reporting will cause client applications > to break. I could be wrong, of course :) > > Patch attached (or course, a final patch will have to change the manual as > well) - thoughts? And add some test coverage. I like it. And it gives us something to tide us over until I've finished libltdl2 in 2012 ;) Cheers, -- Gary V. Vaughan (g...@gnu.org) _______________________________________________ http://lists.gnu.org/mailman/listinfo/libtool