pipewire: fix leak of dbus interface

Track loaded interfaces.
Add a method to release the dbus interface when the core is
destroyed.
Free SDL resources in video-play example
This commit is contained in:
Wim Taymans 2018-09-19 15:58:05 +02:00
parent 9e60fd0b57
commit 8d2a9fcf62
5 changed files with 74 additions and 11 deletions

View file

@ -449,5 +449,9 @@ int main(int argc, char *argv[])
pw_core_destroy(data.core);
pw_main_loop_destroy(data.loop);
SDL_DestroyTexture(data.texture);
SDL_DestroyRenderer(data.renderer);
SDL_DestroyWindow(data.window);
return 0;
}

View file

@ -391,12 +391,14 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, struct pw_properties *pro
spa_graph_init(&this->rt.graph);
spa_graph_set_callbacks(&this->rt.graph, &spa_graph_impl_default, NULL);
this->dbus_iface = pw_get_spa_dbus(this->main_loop);
this->support[0] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, this->type.map);
this->support[1] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__DataLoop, this->data_loop->loop);
this->support[2] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__MainLoop, this->main_loop->loop);
this->support[3] = SPA_SUPPORT_INIT(SPA_TYPE__LoopUtils, this->main_loop->utils);
this->support[4] = SPA_SUPPORT_INIT(SPA_TYPE__Log, pw_log_get());
this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE__DBus, pw_get_spa_dbus(this->main_loop));
this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE__DBus, this->dbus_iface);
this->n_support = 6;
pw_log_debug("%p", this->support[5].data);
@ -494,6 +496,8 @@ void pw_core_destroy(struct pw_core *core)
pw_data_loop_destroy(core->data_loop_impl);
pw_release_spa_dbus(core->dbus_iface);
pw_properties_free(core->properties);
pw_map_clear(&core->globals);

View file

@ -44,6 +44,19 @@ static struct support_info {
uint32_t n_support;
} support_info;
struct interface {
struct spa_list link;
struct spa_handle *handle;
uint32_t type;
void *iface;
};
struct registry {
struct spa_list interfaces;
};
static struct registry global_registry;
static bool
open_support(const char *path,
const char *lib,
@ -92,7 +105,7 @@ static const struct spa_handle_factory *get_factory(struct support_info *info, c
return NULL;
}
static void *
static struct interface *
load_interface(struct support_info *info,
const char *factory_name,
const char *type)
@ -101,7 +114,8 @@ load_interface(struct support_info *info,
struct spa_handle *handle;
uint32_t type_id;
const struct spa_handle_factory *factory;
void *iface;
struct interface *iface;
void *ptr;
struct spa_type_map *map = NULL;
factory = get_factory(info, factory_name);
@ -118,12 +132,22 @@ load_interface(struct support_info *info,
map = pw_get_support_interface(SPA_TYPE__TypeMap);
type_id = map ? spa_type_map_get_id(map, type) : 0;
if ((res = spa_handle_get_interface(handle, type_id, &iface)) < 0) {
if ((res = spa_handle_get_interface(handle, type_id, &ptr)) < 0) {
fprintf(stderr, "can't get %s interface %d\n", type, res);
goto interface_failed;
}
if ((iface = calloc(1, sizeof(struct interface))) == NULL)
goto alloc_failed;
iface->handle = handle;
iface->type = type_id;
iface->iface = ptr;
spa_list_append(&global_registry.interfaces, &iface->link);
return iface;
alloc_failed:
interface_failed:
spa_handle_clear(handle);
init_failed:
@ -175,6 +199,7 @@ void *pw_get_spa_dbus(struct pw_loop *loop)
{
struct support_info dbus_support_info;
const char *str;
struct interface *iface;
dbus_support_info.n_support = support_info.n_support;
memcpy(dbus_support_info.support, support_info.support,
@ -186,11 +211,36 @@ void *pw_get_spa_dbus(struct pw_loop *loop)
if ((str = getenv("SPA_PLUGIN_DIR")) == NULL)
str = PLUGINDIR;
if (open_support(str, "support/libspa-dbus", &dbus_support_info))
return load_interface(&dbus_support_info, "dbus", SPA_TYPE__DBus);
if (open_support(str, "support/libspa-dbus", &dbus_support_info)) {
iface = load_interface(&dbus_support_info, "dbus", SPA_TYPE__DBus);
if (iface != NULL)
return iface->iface;
}
return NULL;
}
static struct interface *find_interface(void *iface)
{
struct interface *i;
spa_list_for_each(i, &global_registry.interfaces, link) {
if (i->iface == iface)
return i;
}
return NULL;
}
int pw_release_spa_dbus(void *dbus)
{
struct interface *iface;
if ((iface = find_interface(dbus)) == NULL)
return -ENOENT;
spa_list_remove(&iface->link);
spa_handle_clear(iface->handle);
free(iface->handle);
free(iface);
return 0;
}
/** Initialize PipeWire
*
@ -207,7 +257,7 @@ void *pw_get_spa_dbus(struct pw_loop *loop)
void pw_init(int *argc, char **argv[])
{
const char *str;
void *iface;
struct interface *iface;
struct support_info *info = &support_info;
if ((str = getenv("PIPEWIRE_DEBUG")))
@ -219,15 +269,17 @@ void pw_init(int *argc, char **argv[])
if (support_info.n_support > 0)
return;
spa_list_init(&global_registry.interfaces);
if (open_support(str, "support/libspa-support", info)) {
iface = load_interface(info, "mapper", SPA_TYPE__TypeMap);
if (iface != NULL)
info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface);
info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface->iface);
iface = load_interface(info, "logger", SPA_TYPE__Log);
if (iface != NULL) {
info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface);
pw_log_set(iface);
info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface->iface);
pw_log_set(iface->iface);
}
}
pw_log_info("version %s", pw_get_library_version());

View file

@ -134,6 +134,7 @@ void *
pw_get_support_interface(const char *type);
void *pw_get_spa_dbus(struct pw_loop *loop);
int pw_release_spa_dbus(void *dbus);
const struct spa_handle_factory *
pw_get_support_factory(const char *factory_name);

View file

@ -183,6 +183,8 @@ struct pw_core {
struct pw_loop *data_loop; /**< data loop for data passing */
struct pw_data_loop *data_loop_impl;
void *dbus_iface;
struct spa_support support[16]; /**< support for spa plugins */
uint32_t n_support; /**< number of support items */