This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
Re: patch 1/2 debuginfod client
Hi,
On Tue, 2019-11-19 at 16:22 -0500, Frank Ch. Eigler wrote:
> On Tue, Nov 19, 2019 at 09:15:20PM +0100, Mark Wielaard wrote:
> > > That's what the doc says. What the code does, as far back as the year
> > > 2001, is have a static flag/counter in curl_global_init() that
> > > prevents multiple initialization.
> >
> > But the warning isn't about multiple initialization. It is about
> > initialization when other threads are running that might be using any
> > of the libcurl support libraries.
>
> Since 2001, the curl_global_init function does nothing to interfere
> with any libcurl activity, if the library is already initialized. Any
> call to the normal libcurl functions first calls this function. I
> guess I just fail to see a plausible problem scenario short of a
> minuscule race over incrementing an initialization counter, which is a
> race that every other libcurl user has accepted.
But it isn't just about interference with other libcurl activity. If
you look at the curl_global_init code you see that it actually calls a
lot of code in other libraries. It is the curl_global_init code that
shouldn't be run in a multi-threaded environment. That it is acceptable
to others doesn't immediately make it safe to use in our case. We are
slowly trying to make libdw.so into a multi-tread safe library and do
expect it to be used in multi-threaded code. We aren't fully there yet.
But it would be a shame to introduce more issues if we can prevent it.
> > > > That is why I think doing the dlopen of libdebuginfod.so eagerly from a
> > > > libdw.so constructor function or _init might be necessary to make sure
> > > > no other threads are running yet.
> > >
> > > That's not even enough for "sure" - if we're so deep in the
> > > hypotheticals hole, an application could be dlopen()ing libdw.so
> > > itself.
> >
> > It could, but I think that would be unlikely. We can at least document
> > that it is unsafe to use libdw.so with dlopen. But if it is done,
> > could we detect it and not do the loading of libdebuginfod.so in that
> > case?
>
> I don't know how to do that.
I assume you mean the second part. The attached is what I would propose
for the first part. Do you think that is a bad idea?
Thanks,
Mark
diff --git a/libdwfl/debuginfod-client.c b/libdwfl/debuginfod-client.c
index 37a4c71f..ee604ad9 100644
--- a/libdwfl/debuginfod-client.c
+++ b/libdwfl/debuginfod-client.c
@@ -46,32 +46,7 @@ get_client (Dwfl *dwfl)
if (dwfl->debuginfod != NULL)
return dwfl->debuginfod;
- if (fp_debuginfod_begin == NULL)
- {
- void *debuginfod_so = dlopen("libdebuginfod-" VERSION ".so", RTLD_LAZY);
-
- if (debuginfod_so == NULL)
- debuginfod_so = dlopen("libdebuginfod.so", RTLD_LAZY);
-
- if (debuginfod_so != NULL)
- {
- fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin");
- fp_debuginfod_find_executable = dlsym (debuginfod_so,
- "debuginfod_find_executable");
- fp_debuginfod_find_debuginfo = dlsym (debuginfod_so,
- "debuginfod_find_debuginfo");
- fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end");
- }
-
- if (fp_debuginfod_begin == NULL
- || fp_debuginfod_find_executable == NULL
- || fp_debuginfod_find_debuginfo == NULL
- || fp_debuginfod_end == NULL)
- fp_debuginfod_begin = (void *) -1; /* never try again */
- }
-
- if (fp_debuginfod_begin != NULL
- && fp_debuginfod_begin != (void *) -1)
+ if (fp_debuginfod_begin != NULL)
{
dwfl->debuginfod = (*fp_debuginfod_begin) ();
return dwfl->debuginfod;
@@ -120,3 +95,37 @@ __libdwfl_debuginfod_end (debuginfod_client *c)
if (c != NULL)
(*fp_debuginfod_end) (c);
}
+
+/* Try to get the libdebuginfod library functions to make sure
+ everything is initialized early. */
+void __attribute__ ((constructor))
+__libdwfl_debuginfod_init (void)
+{
+ void *debuginfod_so = dlopen("libdebuginfod-" VERSION ".so", RTLD_LAZY);
+
+ if (debuginfod_so == NULL)
+ debuginfod_so = dlopen("libdebuginfod.so", RTLD_LAZY);
+
+ if (debuginfod_so != NULL)
+ {
+ fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin");
+ fp_debuginfod_find_executable = dlsym (debuginfod_so,
+ "debuginfod_find_executable");
+ fp_debuginfod_find_debuginfo = dlsym (debuginfod_so,
+ "debuginfod_find_debuginfo");
+ fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end");
+
+ /* We either get them all, or we get none. */
+ if (fp_debuginfod_begin == NULL
+ || fp_debuginfod_find_executable == NULL
+ || fp_debuginfod_find_debuginfo == NULL
+ || fp_debuginfod_end == NULL)
+ {
+ fp_debuginfod_begin = NULL;
+ fp_debuginfod_find_executable = NULL;
+ fp_debuginfod_find_debuginfo = NULL;
+ fp_debuginfod_end = NULL;
+ dlclose (debuginfod_so);
+ }
+ }
+}