mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -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;
|
||||
const char *plugin_dir;
|
||||
const char *support_lib;
|
||||
struct registry *registry;
|
||||
struct registry registry;
|
||||
char *i18n_domain;
|
||||
struct spa_interface i18n_iface;
|
||||
struct spa_support support[MAX_SUPPORT];
|
||||
uint32_t n_support;
|
||||
unsigned int initialized:1;
|
||||
unsigned int in_valgrind:1;
|
||||
unsigned int no_color: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 plugin *
|
||||
|
|
@ -242,8 +244,7 @@ uint32_t pw_get_support(struct spa_support *support, uint32_t max_support)
|
|||
return n;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
struct spa_handle *pw_load_spa_handle(const char *lib,
|
||||
static struct spa_handle *load_spa_handle(const char *lib,
|
||||
const char *factory_name,
|
||||
const struct spa_dict *info,
|
||||
uint32_t n_support,
|
||||
|
|
@ -271,13 +272,15 @@ struct spa_handle *pw_load_spa_handle(const char *lib,
|
|||
res = -ENOENT;
|
||||
|
||||
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;
|
||||
res = -errno;
|
||||
}
|
||||
if (plugin == NULL)
|
||||
goto error_out;
|
||||
|
||||
pthread_mutex_unlock(&support_lock);
|
||||
|
||||
factory = find_factory(plugin, factory_name);
|
||||
if (factory == NULL) {
|
||||
res = -errno;
|
||||
|
|
@ -298,6 +301,7 @@ struct spa_handle *pw_load_spa_handle(const char *lib,
|
|||
goto error_free_handle;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&support_lock);
|
||||
handle->ref = 1;
|
||||
handle->plugin = plugin;
|
||||
handle->factory_name = strdup(factory_name);
|
||||
|
|
@ -308,15 +312,30 @@ struct spa_handle *pw_load_spa_handle(const char *lib,
|
|||
error_free_handle:
|
||||
free(handle);
|
||||
error_unref_plugin:
|
||||
pthread_mutex_lock(&support_lock);
|
||||
unref_plugin(plugin);
|
||||
error_out:
|
||||
errno = -res;
|
||||
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)
|
||||
{
|
||||
struct registry *registry = global_support.registry;
|
||||
struct registry *registry = &global_support.registry;
|
||||
struct plugin *p;
|
||||
struct handle *h;
|
||||
|
||||
|
|
@ -333,13 +352,16 @@ SPA_EXPORT
|
|||
int pw_unload_spa_handle(struct spa_handle *handle)
|
||||
{
|
||||
struct handle *h;
|
||||
int res = 0;
|
||||
|
||||
pthread_mutex_lock(&support_lock);
|
||||
if ((h = find_handle(handle)) == NULL)
|
||||
return -ENOENT;
|
||||
res = -ENOENT;
|
||||
else
|
||||
unref_handle(h);
|
||||
pthread_mutex_unlock(&support_lock);
|
||||
|
||||
unref_handle(h);
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static void *add_interface(struct support *support,
|
||||
|
|
@ -351,17 +373,24 @@ static void *add_interface(struct support *support,
|
|||
void *iface = NULL;
|
||||
int res = -ENOENT;
|
||||
|
||||
handle = pw_load_spa_handle(support->support_lib,
|
||||
handle = load_spa_handle(support->support_lib,
|
||||
factory_name, info,
|
||||
support->n_support, support->support);
|
||||
if (handle == NULL)
|
||||
return NULL;
|
||||
|
||||
if (handle == NULL ||
|
||||
(res = spa_handle_get_interface(handle, type, &iface)) < 0) {
|
||||
pw_log_error("can't get %s interface %d", type, res);
|
||||
} else {
|
||||
support->support[support->n_support++] =
|
||||
SPA_SUPPORT_INIT(type, iface);
|
||||
pthread_mutex_unlock(&support_lock);
|
||||
res = spa_handle_get_interface(handle, type, &iface);
|
||||
pthread_mutex_lock(&support_lock);
|
||||
|
||||
if (res < 0 || iface == NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -376,6 +405,7 @@ int pw_set_domain(const char *domain)
|
|||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
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);
|
||||
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,
|
||||
support->n_support, support->support);
|
||||
if (handle == NULL)
|
||||
return NULL;
|
||||
|
||||
if (handle == NULL ||
|
||||
(res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Log, &iface)) < 0) {
|
||||
pw_log_error("can't get log interface %d", res);
|
||||
} else {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&support_lock);
|
||||
res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Log, &iface);
|
||||
pthread_mutex_lock(&support_lock);
|
||||
|
||||
if (res < 0 || iface == NULL) {
|
||||
pw_log_error("can't get log interface %d: %s", res,
|
||||
spa_strerror(res));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -502,9 +538,11 @@ void pw_init(int *argc, char **argv[])
|
|||
struct spa_log *log;
|
||||
char level[32];
|
||||
|
||||
if (support->registry != NULL)
|
||||
return;
|
||||
pthread_mutex_lock(&init_lock);
|
||||
if (support->initialized)
|
||||
goto done;
|
||||
|
||||
pthread_mutex_lock(&support_lock);
|
||||
support->in_valgrind = RUNNING_ON_VALGRIND;
|
||||
|
||||
if (getenv("NO_COLOR") != NULL)
|
||||
|
|
@ -526,8 +564,7 @@ void pw_init(int *argc, char **argv[])
|
|||
str = SUPPORTLIB;
|
||||
support->support_lib = str;
|
||||
|
||||
spa_list_init(&global_registry.plugins);
|
||||
support->registry = &global_registry;
|
||||
spa_list_init(&support->registry.plugins);
|
||||
|
||||
if (pw_log_is_default()) {
|
||||
n_items = 0;
|
||||
|
|
@ -569,15 +606,21 @@ void pw_init(int *argc, char **argv[])
|
|||
add_i18n(support);
|
||||
|
||||
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
|
||||
void pw_deinit(void)
|
||||
{
|
||||
struct support *support = &global_support;
|
||||
struct registry *registry = &global_registry;
|
||||
struct registry *registry = &support->registry;
|
||||
struct plugin *p;
|
||||
|
||||
pthread_mutex_lock(&init_lock);
|
||||
pthread_mutex_lock(&support_lock);
|
||||
pw_log_set(NULL);
|
||||
spa_list_consume(p, ®istry->plugins, link) {
|
||||
struct handle *h;
|
||||
|
|
@ -589,7 +632,8 @@ void pw_deinit(void)
|
|||
pw_free_strv(support->categories);
|
||||
free(support->i18n_domain);
|
||||
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