cli-command: don't exit on "module already loaded" errors

Some modules may only be loaded once, and trying to load them
twice from default.pa makes PulseAudio startup fail. While that could
be considered a user error, it's nicer to not be so strict. It's not
necessarily easy to figure what went wrong, if for example the user
plays with RAOP and adds module-raop-discover to default.pa, which first
works fine, but suddenly stops working when the user at some point
enables RAOP support in paprefs. Enabling RAOP in paprefs makes
module-gconf load the module too, so the module gets loaded twice.

This patch adds a way to differentiate module load errors, and
make cli-command ignore the error when the module is already
loaded.
This commit is contained in:
Colin Leroy 2017-08-26 11:21:15 +02:00 committed by Tanu Kaskinen
parent 1a66715320
commit f0dfddead3
23 changed files with 62 additions and 36 deletions

View file

@ -421,6 +421,8 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool
static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
const char *name;
pa_error_code_t err;
pa_module *m = NULL;
pa_core_assert_ref(c);
pa_assert(t);
@ -432,9 +434,13 @@ static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool
return -1;
}
if (!pa_module_load(c, name, pa_tokenizer_get(t, 2))) {
pa_strbuf_puts(buf, "Module load failed.\n");
return -1;
if ((err = pa_module_load(&m, c, name, pa_tokenizer_get(t, 2))) < 0) {
if (err == PA_ERR_EXIST) {
pa_strbuf_puts(buf, "Module already loaded; ignoring.\n");
} else {
pa_strbuf_puts(buf, "Module load failed.\n");
return -1;
}
}
return 0;

View file

@ -107,17 +107,21 @@ void pa_module_hook_connect(pa_module *m, pa_hook *hook, pa_hook_priority_t prio
pa_dynarray_append(m->hooks, pa_hook_connect(hook, prio, cb, data));
}
pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
int pa_module_load(pa_module** module, pa_core *c, const char *name, const char *argument) {
pa_module *m = NULL;
bool (*load_once)(void);
const char* (*get_deprecated)(void);
pa_modinfo *mi;
int errcode;
pa_assert(module);
pa_assert(c);
pa_assert(name);
if (c->disallow_module_loading)
if (c->disallow_module_loading) {
errcode = -PA_ERR_ACCESS;
goto fail;
}
m = pa_xnew(pa_module, 1);
m->name = pa_xstrdup(name);
@ -135,6 +139,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
* loader, which never finds anything, and therefore says "file not
* found". */
pa_log("Failed to open module \"%s\".", name);
errcode = -PA_ERR_IO;
goto fail;
}
@ -150,6 +155,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
PA_IDXSET_FOREACH(i, c->modules, idx) {
if (pa_streq(name, i->name)) {
pa_log("Module \"%s\" should be loaded once at most. Refusing to load.", name);
errcode = -PA_ERR_EXIST;
goto fail;
}
}
@ -165,6 +171,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
if (!(m->init = (int (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_INIT))) {
pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name);
errcode = -PA_ERR_IO;
goto fail;
}
@ -179,6 +186,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
if (m->init(m) < 0) {
pa_log_error("Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
errcode = -PA_ERR_IO;
goto fail;
}
@ -202,7 +210,9 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
pa_hook_fire(&m->core->hooks[PA_CORE_HOOK_MODULE_NEW], m);
return m;
*module = m;
return 0;
fail:
@ -225,7 +235,9 @@ fail:
pa_xfree(m);
}
return NULL;
*module = NULL;
return errcode;
}
static void postponed_dlclose(pa_mainloop_api *api, void *userdata) {

View file

@ -52,7 +52,7 @@ struct pa_module {
bool pa_module_exists(const char *name);
pa_module* pa_module_load(pa_core *c, const char *name, const char *argument);
int pa_module_load(pa_module** m, pa_core *c, const char *name, const char *argument);
void pa_module_unload(pa_module *m, bool force);
void pa_module_unload_by_index(pa_core *c, uint32_t idx, bool force);

View file

@ -4468,7 +4468,7 @@ static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag
CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
if (!(m = pa_module_load(c->protocol->core, name, argument))) {
if (pa_module_load(&m, c->protocol->core, name, argument) < 0) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
return;
}