mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
pipewire: use lock for registry and init
Use a global lock to serialize concurrent pw_init calls. Use a global lock to protect the global registry. With the alsa api, multiple threads could open the device and create streams and load/unload plugins. See !942
This commit is contained in:
parent
e8e7e72b76
commit
68f4dee2d9
1 changed files with 80 additions and 36 deletions
|
|
@ -81,17 +81,19 @@ struct support {
|
||||||
char **categories;
|
char **categories;
|
||||||
const char *plugin_dir;
|
const char *plugin_dir;
|
||||||
const char *support_lib;
|
const char *support_lib;
|
||||||
struct registry *registry;
|
struct registry registry;
|
||||||
char *i18n_domain;
|
char *i18n_domain;
|
||||||
struct spa_interface i18n_iface;
|
struct spa_interface i18n_iface;
|
||||||
struct spa_support support[MAX_SUPPORT];
|
struct spa_support support[MAX_SUPPORT];
|
||||||
uint32_t n_support;
|
uint32_t n_support;
|
||||||
|
unsigned int initialized:1;
|
||||||
unsigned int in_valgrind:1;
|
unsigned int in_valgrind:1;
|
||||||
unsigned int no_color:1;
|
unsigned int no_color:1;
|
||||||
unsigned int no_config:1;
|
unsigned int no_config:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct registry global_registry;
|
static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_mutex_t support_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static struct support global_support;
|
static struct support global_support;
|
||||||
|
|
||||||
static struct plugin *
|
static struct plugin *
|
||||||
|
|
@ -242,8 +244,7 @@ uint32_t pw_get_support(struct spa_support *support, uint32_t max_support)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
static struct spa_handle *load_spa_handle(const char *lib,
|
||||||
struct spa_handle *pw_load_spa_handle(const char *lib,
|
|
||||||
const char *factory_name,
|
const char *factory_name,
|
||||||
const struct spa_dict *info,
|
const struct spa_dict *info,
|
||||||
uint32_t n_support,
|
uint32_t n_support,
|
||||||
|
|
@ -271,13 +272,15 @@ struct spa_handle *pw_load_spa_handle(const char *lib,
|
||||||
res = -ENOENT;
|
res = -ENOENT;
|
||||||
|
|
||||||
while ((p = pw_split_walk(sup->plugin_dir, ":", &len, &state))) {
|
while ((p = pw_split_walk(sup->plugin_dir, ":", &len, &state))) {
|
||||||
if ((plugin = open_plugin(sup->registry, p, len, lib)) != NULL)
|
if ((plugin = open_plugin(&sup->registry, p, len, lib)) != NULL)
|
||||||
break;
|
break;
|
||||||
res = -errno;
|
res = -errno;
|
||||||
}
|
}
|
||||||
if (plugin == NULL)
|
if (plugin == NULL)
|
||||||
goto error_out;
|
goto error_out;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&support_lock);
|
||||||
|
|
||||||
factory = find_factory(plugin, factory_name);
|
factory = find_factory(plugin, factory_name);
|
||||||
if (factory == NULL) {
|
if (factory == NULL) {
|
||||||
res = -errno;
|
res = -errno;
|
||||||
|
|
@ -298,6 +301,7 @@ struct spa_handle *pw_load_spa_handle(const char *lib,
|
||||||
goto error_free_handle;
|
goto error_free_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&support_lock);
|
||||||
handle->ref = 1;
|
handle->ref = 1;
|
||||||
handle->plugin = plugin;
|
handle->plugin = plugin;
|
||||||
handle->factory_name = strdup(factory_name);
|
handle->factory_name = strdup(factory_name);
|
||||||
|
|
@ -308,15 +312,30 @@ struct spa_handle *pw_load_spa_handle(const char *lib,
|
||||||
error_free_handle:
|
error_free_handle:
|
||||||
free(handle);
|
free(handle);
|
||||||
error_unref_plugin:
|
error_unref_plugin:
|
||||||
|
pthread_mutex_lock(&support_lock);
|
||||||
unref_plugin(plugin);
|
unref_plugin(plugin);
|
||||||
error_out:
|
error_out:
|
||||||
errno = -res;
|
errno = -res;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPA_EXPORT
|
||||||
|
struct spa_handle *pw_load_spa_handle(const char *lib,
|
||||||
|
const char *factory_name,
|
||||||
|
const struct spa_dict *info,
|
||||||
|
uint32_t n_support,
|
||||||
|
const struct spa_support support[])
|
||||||
|
{
|
||||||
|
struct spa_handle *handle;
|
||||||
|
pthread_mutex_lock(&support_lock);
|
||||||
|
handle = load_spa_handle(lib, factory_name, info, n_support, support);
|
||||||
|
pthread_mutex_unlock(&support_lock);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
static struct handle *find_handle(struct spa_handle *handle)
|
static struct handle *find_handle(struct spa_handle *handle)
|
||||||
{
|
{
|
||||||
struct registry *registry = global_support.registry;
|
struct registry *registry = &global_support.registry;
|
||||||
struct plugin *p;
|
struct plugin *p;
|
||||||
struct handle *h;
|
struct handle *h;
|
||||||
|
|
||||||
|
|
@ -333,13 +352,16 @@ SPA_EXPORT
|
||||||
int pw_unload_spa_handle(struct spa_handle *handle)
|
int pw_unload_spa_handle(struct spa_handle *handle)
|
||||||
{
|
{
|
||||||
struct handle *h;
|
struct handle *h;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&support_lock);
|
||||||
if ((h = find_handle(handle)) == NULL)
|
if ((h = find_handle(handle)) == NULL)
|
||||||
return -ENOENT;
|
res = -ENOENT;
|
||||||
|
else
|
||||||
|
unref_handle(h);
|
||||||
|
pthread_mutex_unlock(&support_lock);
|
||||||
|
|
||||||
unref_handle(h);
|
return res;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *add_interface(struct support *support,
|
static void *add_interface(struct support *support,
|
||||||
|
|
@ -351,17 +373,24 @@ static void *add_interface(struct support *support,
|
||||||
void *iface = NULL;
|
void *iface = NULL;
|
||||||
int res = -ENOENT;
|
int res = -ENOENT;
|
||||||
|
|
||||||
handle = pw_load_spa_handle(support->support_lib,
|
handle = load_spa_handle(support->support_lib,
|
||||||
factory_name, info,
|
factory_name, info,
|
||||||
support->n_support, support->support);
|
support->n_support, support->support);
|
||||||
|
if (handle == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (handle == NULL ||
|
pthread_mutex_unlock(&support_lock);
|
||||||
(res = spa_handle_get_interface(handle, type, &iface)) < 0) {
|
res = spa_handle_get_interface(handle, type, &iface);
|
||||||
pw_log_error("can't get %s interface %d", type, res);
|
pthread_mutex_lock(&support_lock);
|
||||||
} else {
|
|
||||||
support->support[support->n_support++] =
|
if (res < 0 || iface == NULL) {
|
||||||
SPA_SUPPORT_INIT(type, iface);
|
pw_log_error("can't get %s interface %d: %s", type, res,
|
||||||
|
spa_strerror(res));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
support->support[support->n_support++] =
|
||||||
|
SPA_SUPPORT_INIT(type, iface);
|
||||||
return iface;
|
return iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,6 +405,7 @@ int pw_set_domain(const char *domain)
|
||||||
return -errno;
|
return -errno;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
const char *pw_get_domain(void)
|
const char *pw_get_domain(void)
|
||||||
{
|
{
|
||||||
|
|
@ -458,24 +488,30 @@ static struct spa_log *load_journal_logger(struct support *support)
|
||||||
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_LEVEL, level);
|
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_LEVEL, level);
|
||||||
info = SPA_DICT_INIT(items, 1);
|
info = SPA_DICT_INIT(items, 1);
|
||||||
|
|
||||||
handle = pw_load_spa_handle("support/libspa-journal",
|
handle = load_spa_handle("support/libspa-journal",
|
||||||
SPA_NAME_SUPPORT_LOG, &info,
|
SPA_NAME_SUPPORT_LOG, &info,
|
||||||
support->n_support, support->support);
|
support->n_support, support->support);
|
||||||
|
if (handle == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (handle == NULL ||
|
pthread_mutex_unlock(&support_lock);
|
||||||
(res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Log, &iface)) < 0) {
|
res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Log, &iface);
|
||||||
pw_log_error("can't get log interface %d", res);
|
pthread_mutex_lock(&support_lock);
|
||||||
} else {
|
|
||||||
/* look for an existing logger, and
|
if (res < 0 || iface == NULL) {
|
||||||
* replace it with the journal logger */
|
pw_log_error("can't get log interface %d: %s", res,
|
||||||
for (i = 0; i < support->n_support; i++) {
|
spa_strerror(res));
|
||||||
if (spa_streq(support->support[i].type, SPA_TYPE_INTERFACE_Log)) {
|
return NULL;
|
||||||
support->support[i].data = iface;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* look for an existing logger, and
|
||||||
|
* replace it with the journal logger */
|
||||||
|
for (i = 0; i < support->n_support; i++) {
|
||||||
|
if (spa_streq(support->support[i].type, SPA_TYPE_INTERFACE_Log)) {
|
||||||
|
support->support[i].data = iface;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return (struct spa_log *) iface;
|
return (struct spa_log *) iface;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -502,9 +538,11 @@ void pw_init(int *argc, char **argv[])
|
||||||
struct spa_log *log;
|
struct spa_log *log;
|
||||||
char level[32];
|
char level[32];
|
||||||
|
|
||||||
if (support->registry != NULL)
|
pthread_mutex_lock(&init_lock);
|
||||||
return;
|
if (support->initialized)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&support_lock);
|
||||||
support->in_valgrind = RUNNING_ON_VALGRIND;
|
support->in_valgrind = RUNNING_ON_VALGRIND;
|
||||||
|
|
||||||
if (getenv("NO_COLOR") != NULL)
|
if (getenv("NO_COLOR") != NULL)
|
||||||
|
|
@ -526,8 +564,7 @@ void pw_init(int *argc, char **argv[])
|
||||||
str = SUPPORTLIB;
|
str = SUPPORTLIB;
|
||||||
support->support_lib = str;
|
support->support_lib = str;
|
||||||
|
|
||||||
spa_list_init(&global_registry.plugins);
|
spa_list_init(&support->registry.plugins);
|
||||||
support->registry = &global_registry;
|
|
||||||
|
|
||||||
if (pw_log_is_default()) {
|
if (pw_log_is_default()) {
|
||||||
n_items = 0;
|
n_items = 0;
|
||||||
|
|
@ -569,15 +606,21 @@ void pw_init(int *argc, char **argv[])
|
||||||
add_i18n(support);
|
add_i18n(support);
|
||||||
|
|
||||||
pw_log_info("version %s", pw_get_library_version());
|
pw_log_info("version %s", pw_get_library_version());
|
||||||
|
support->initialized = true;
|
||||||
|
pthread_mutex_unlock(&support_lock);
|
||||||
|
done:
|
||||||
|
pthread_mutex_unlock(&init_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
void pw_deinit(void)
|
void pw_deinit(void)
|
||||||
{
|
{
|
||||||
struct support *support = &global_support;
|
struct support *support = &global_support;
|
||||||
struct registry *registry = &global_registry;
|
struct registry *registry = &support->registry;
|
||||||
struct plugin *p;
|
struct plugin *p;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&init_lock);
|
||||||
|
pthread_mutex_lock(&support_lock);
|
||||||
pw_log_set(NULL);
|
pw_log_set(NULL);
|
||||||
spa_list_consume(p, ®istry->plugins, link) {
|
spa_list_consume(p, ®istry->plugins, link) {
|
||||||
struct handle *h;
|
struct handle *h;
|
||||||
|
|
@ -589,7 +632,8 @@ void pw_deinit(void)
|
||||||
pw_free_strv(support->categories);
|
pw_free_strv(support->categories);
|
||||||
free(support->i18n_domain);
|
free(support->i18n_domain);
|
||||||
spa_zero(global_support);
|
spa_zero(global_support);
|
||||||
spa_zero(global_registry);
|
pthread_mutex_unlock(&support_lock);
|
||||||
|
pthread_mutex_unlock(&init_lock);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue