Module Loading

PulseAudio is built on an extensible platfrom: a tight core with a huge number of modules around providing various features. I am currently bugfixing a bug related to modules loading, and thus the need for exploring this issue further arised.

First things first, when running PA, you can send a parameter telling it where its modules directory exist. Quoting the documentation:

-p | --dl-search-path=PATH
    Set the search path for dynamic shared objects (plugins).

PulseAudio uses libtool for modules loading. Here is the full documentation manual for libtool.

Initialization

In the early parts of the daemon initialization at src/daemon/main.c, we can see that:

    LTDL_SET_PRELOADED_SYMBOLS();
    pa_ltdl_init();
    ltdl_init = true;

As said by the goat book, LTDL_SET_PRELOADED_SYMBOLS() populate the lookup table with static entries. This is done to let libtool to fallback to load preloaded static modules if we instruct it to do so, or for targets that does not support native dynamic loading.

Afterwards, we jump to the the PulseAudio libtool dynamic loading init at src/daemon/ltdl_bind_now.c:

void pa_ltdl_init(void) {

#ifdef PA_BIND_NOW
    const lt_dlvtable *dlopen_loader;
#endif

    pa_assert_se(lt_dlinit() == 0);

#ifdef PA_BIND_NOW
    /* Already initialised */
    if (bindnow_loader)
        return;

    if (!(dlopen_loader = lt_dlloader_find((char*) "lt_dlopen"))) {
        pa_log_warn(_("Failed to find original lt_dlopen loader."));
        return;
    }

    if (!(bindnow_loader = malloc(sizeof(lt_dlvtable)))) {
        pa_log_error(_("Failed to allocate new dl loader."));
        return;
    }

    memcpy(bindnow_loader, dlopen_loader, sizeof(*bindnow_loader));
    bindnow_loader->name = "bind-now-loader";
    bindnow_loader->module_open = bind_now_open;
    bindnow_loader->module_close = bind_now_close;
    bindnow_loader->find_sym = bind_now_find_sym;
    bindnow_loader->priority = LT_DLLOADER_PREPEND;

    /* Add our BIND_NOW loader as the default module loader. */
    if (lt_dlloader_add(bindnow_loader) != 0) {
        pa_log_warn(_("Failed to add bind-now-loader."));
        free(bindnow_loader);
        bindnow_loader = NULL;
    }
#endif
}

As can be seen from above, PulseAudio actually creates its own dynamic libraries loader. As said by the libtool official manual, lt_dlloader_add is used to implement custom module loaders.

PA implements its own custom module loader to do shared libraries binding on module loading time instead of lazily on method/symbol invocation time. Check the dlopen(3) manpage, and specifically the RTLD_LAZY and RTLD_NOW flags for further details.

References

results matching ""

    No results matching ""