No subject


Thu Jan 15 22:29:28 CST 2009


first pass modules with global symbols are loaded and in the second all
of the rest are. This happens so that modules that use those global
symbols won't execute before those symbols become available.

Because the flag that marks a module as providing global symbols is
inside the module, the dynamic loader opens the module with RTLD_LAZY
(so that it won't resolve the possibly unknown so far symbols) and
checks for the flag.
After that, if the module had AST_MODFLAG_GLOBAL_SYMBOLS it promotes it
to RTLD_LAZY | RTLD_GLOBAL. If it didn't, it dlclose()s it is on the
first pass or promotes it to RTLD_NOW if it is on the second.

So far, I can see (but I may be far wrong) the following issues:
a) AFAIK,
RTLD_NOLOAD | RTLD_NOW | RTLD_LOCAL after a RTLD_LAZY | RTLD_LOCAL is a
no-op.
RTLD_NOLOAD is for promoting to RTLD_LOCAL/GLOBAL only. You can
"promote" to RTLD_NOW by re-calling dlopen() (and bumping the reference
count) without closing it first.

This is not documented clearly anywhere and I'm not sure about why;
someone wants to volunteer in contacting the glibc maintainers? :)

It took me some time to pinpoint after my Asterisk has been running for
days with a chan_h323 that couldn't get all of its symbols resolved (see
#10559).

b) Subsequently, there is no reason to do the whole "open with LAZY then
promote" when running the second pass.

c) There is no point on dlclose()ing the modules not providing global
symbols after the first pass; they will be loaded, eventually.

d) There is point on trying to dlopen() a second time the modules that
were loaded on the first pass. OTOH, it doesn't matter much since this
is a low overhead operation (the reference count just bumps without
actual reload happening).

So, in summary:

For modules _not_ providing global symbols, today one gets something
like that when using e.g. ltrace:
  dlopen("chan_foo.so", RTLD_LAZY | RTLD_LOCAL);
  dlclose("chan_foo.so");
  dlopen("chan_foo.so", RTLD_LAZY, RTLD_LOCAL);
  dlopen("chan_foo.so", RTLD_NOLOAD | RTLD_NOW, RTLD_LOCAL); [no-op]

While it could just be:
  dlopen("chan_foo.so", RTLD_LAZY | RTLD_LOCAL);
  dlopen("chan_foo.so", RTLD_NOW | RTLD_LOCAL);

For the modules providing global symbols one gets:
  dlopen("res_foo.so", RTLD_LAZY | RTLD_LOCAL);
  dlopen("res_foo.so", RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LOCAL);
  dlopen("res_foo.so", RTLD_LAZY, RTLD_LOCAL);
  dlopen("res_foo.so", RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LOCAL);

While it could just be the first half of it.

I'm willing to make this happen with code but I'd like to get your input
first in case I'm missing something.

========

Regards,
Faidon



More information about the asterisk-dev mailing list