mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
dbus: clean up sources and connections
Set source user data for all dbus sources and set a destroy notify when removed. Remove the dbus user data to remove the source user data. Clean up remaining sources when destoying a connection Clean up remaining connections when freeing the dbus plugins. Fixes #1114
This commit is contained in:
parent
85b136d8ce
commit
ebe5fa7809
1 changed files with 63 additions and 38 deletions
|
|
@ -50,6 +50,12 @@ struct impl {
|
|||
struct spa_list connection_list;
|
||||
};
|
||||
|
||||
struct source_data {
|
||||
struct spa_list link;
|
||||
struct spa_source *source;
|
||||
struct connection *conn;
|
||||
};
|
||||
|
||||
struct connection {
|
||||
struct spa_list link;
|
||||
|
||||
|
|
@ -57,8 +63,20 @@ struct connection {
|
|||
struct impl *impl;
|
||||
DBusConnection *conn;
|
||||
struct spa_source *dispatch_event;
|
||||
struct spa_list source_list;
|
||||
};
|
||||
|
||||
static void source_data_free(void *data)
|
||||
{
|
||||
struct source_data *d = data;
|
||||
struct connection *conn = d->conn;
|
||||
struct impl *impl = conn->impl;
|
||||
|
||||
spa_list_remove(&d->link);
|
||||
spa_loop_utils_destroy_source(impl->utils, d->source);
|
||||
free(d);
|
||||
}
|
||||
|
||||
static void dispatch_cb(void *userdata)
|
||||
{
|
||||
struct connection *conn = userdata;
|
||||
|
|
@ -128,17 +146,20 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *userdata)
|
|||
{
|
||||
struct connection *conn = userdata;
|
||||
struct impl *impl = conn->impl;
|
||||
struct spa_source *source;
|
||||
struct source_data *data;
|
||||
|
||||
spa_log_debug(impl->log, "add watch %p %d", watch, dbus_watch_get_unix_fd(watch));
|
||||
|
||||
data = calloc(1, sizeof(struct source_data));
|
||||
data->conn = conn;
|
||||
/* we dup because dbus tends to add the same fd multiple times and our epoll
|
||||
* implementation does not like that */
|
||||
source = spa_loop_utils_add_io(impl->utils,
|
||||
data->source = spa_loop_utils_add_io(impl->utils,
|
||||
dup(dbus_watch_get_unix_fd(watch)),
|
||||
dbus_to_io(watch), true, handle_io_event, watch);
|
||||
spa_list_append(&conn->source_list, &data->link);
|
||||
|
||||
dbus_watch_set_data(watch, source, NULL);
|
||||
dbus_watch_set_data(watch, data, source_data_free);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -146,39 +167,29 @@ static void remove_watch(DBusWatch *watch, void *userdata)
|
|||
{
|
||||
struct connection *conn = userdata;
|
||||
struct impl *impl = conn->impl;
|
||||
struct spa_source *source;
|
||||
|
||||
spa_log_debug(impl->log, "remove watch %p", watch);
|
||||
|
||||
if ((source = dbus_watch_get_data(watch)))
|
||||
spa_loop_utils_destroy_source(conn->impl->utils, source);
|
||||
dbus_watch_set_data(watch, NULL, NULL);
|
||||
}
|
||||
|
||||
static void toggle_watch(DBusWatch *watch, void *userdata)
|
||||
{
|
||||
struct connection *conn = userdata;
|
||||
struct impl *impl = conn->impl;
|
||||
struct spa_source *source;
|
||||
struct source_data *data;
|
||||
|
||||
spa_log_debug(impl->log, "toggle watch %p", watch);
|
||||
|
||||
source = dbus_watch_get_data(watch);
|
||||
|
||||
spa_loop_utils_update_io(impl->utils, source, dbus_to_io(watch));
|
||||
if ((data = dbus_watch_get_data(watch)) != NULL)
|
||||
spa_loop_utils_update_io(impl->utils, data->source, dbus_to_io(watch));
|
||||
}
|
||||
|
||||
struct timeout_data {
|
||||
struct spa_source *source;
|
||||
struct connection *conn;
|
||||
};
|
||||
|
||||
static void
|
||||
handle_timer_event(void *userdata, uint64_t expirations)
|
||||
{
|
||||
DBusTimeout *timeout = userdata;
|
||||
uint64_t t;
|
||||
struct timespec ts;
|
||||
struct timeout_data *data = dbus_timeout_get_data(timeout);
|
||||
struct source_data *data = dbus_timeout_get_data(timeout);
|
||||
struct connection *conn = data->conn;
|
||||
struct impl *impl = conn->impl;
|
||||
|
||||
|
|
@ -199,7 +210,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *userdata)
|
|||
struct connection *conn = userdata;
|
||||
struct impl *impl = conn->impl;
|
||||
struct timespec ts;
|
||||
struct timeout_data *data;
|
||||
struct source_data *data;
|
||||
uint64_t t;
|
||||
|
||||
if (!dbus_timeout_get_enabled(timeout))
|
||||
|
|
@ -207,10 +218,12 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *userdata)
|
|||
|
||||
spa_log_debug(impl->log, "add timeout %p conn:%p impl:%p", timeout, conn, impl);
|
||||
|
||||
data = calloc(1, sizeof(struct timeout_data));
|
||||
data = calloc(1, sizeof(struct source_data));
|
||||
data->conn = conn;
|
||||
data->source = spa_loop_utils_add_timer(impl->utils, handle_timer_event, timeout);
|
||||
dbus_timeout_set_data(timeout, data, NULL);
|
||||
spa_list_append(&conn->source_list, &data->link);
|
||||
|
||||
dbus_timeout_set_data(timeout, data, source_data_free);
|
||||
|
||||
t = dbus_timeout_get_interval(timeout) * SPA_NSEC_PER_MSEC;
|
||||
ts.tv_sec = t / SPA_NSEC_PER_SEC;
|
||||
|
|
@ -224,21 +237,15 @@ static void remove_timeout(DBusTimeout *timeout, void *userdata)
|
|||
{
|
||||
struct connection *conn = userdata;
|
||||
struct impl *impl = conn->impl;
|
||||
struct timeout_data *data;
|
||||
|
||||
spa_log_debug(impl->log, "remove timeout %p conn:%p impl:%p", timeout, conn, impl);
|
||||
|
||||
if ((data = dbus_timeout_get_data(timeout))) {
|
||||
spa_loop_utils_destroy_source(impl->utils, data->source);
|
||||
free(data);
|
||||
}
|
||||
dbus_timeout_set_data(timeout, NULL, NULL);
|
||||
}
|
||||
|
||||
static void toggle_timeout(DBusTimeout *timeout, void *userdata)
|
||||
{
|
||||
struct connection *conn = userdata;
|
||||
struct impl *impl = conn->impl;
|
||||
struct timeout_data *data;
|
||||
struct source_data *data;
|
||||
struct timespec ts, *tsp;
|
||||
|
||||
data = dbus_timeout_get_data(timeout);
|
||||
|
|
@ -271,6 +278,24 @@ impl_connection_get(struct spa_dbus_connection *conn)
|
|||
return this->conn;
|
||||
}
|
||||
|
||||
static void connection_free(struct connection *conn)
|
||||
{
|
||||
struct impl *impl = conn->impl;
|
||||
struct source_data *data;
|
||||
|
||||
spa_list_remove(&conn->link);
|
||||
|
||||
dbus_connection_close(conn->conn);
|
||||
dbus_connection_unref(conn->conn);
|
||||
|
||||
spa_list_consume(data, &conn->source_list, link)
|
||||
source_data_free(data);
|
||||
|
||||
spa_loop_utils_destroy_source(impl->utils, conn->dispatch_event);
|
||||
|
||||
free(conn);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_connection_destroy(struct spa_dbus_connection *conn)
|
||||
{
|
||||
|
|
@ -278,15 +303,7 @@ impl_connection_destroy(struct spa_dbus_connection *conn)
|
|||
struct impl *impl = this->impl;
|
||||
|
||||
spa_log_debug(impl->log, "destroy conn %p", this);
|
||||
|
||||
dbus_connection_close(this->conn);
|
||||
dbus_connection_unref(this->conn);
|
||||
|
||||
spa_loop_utils_destroy_source(impl->utils, this->dispatch_event);
|
||||
|
||||
spa_list_remove(&this->link);
|
||||
|
||||
free(this);
|
||||
connection_free(this);
|
||||
}
|
||||
|
||||
static const struct spa_dbus_connection impl_connection = {
|
||||
|
|
@ -318,6 +335,8 @@ impl_get_connection(void *object,
|
|||
if (conn->dispatch_event == NULL)
|
||||
goto no_event;
|
||||
|
||||
spa_list_init(&conn->source_list);
|
||||
|
||||
dbus_connection_set_exit_on_disconnect(conn->conn, false);
|
||||
dbus_connection_set_dispatch_status_function(conn->conn, dispatch_status, conn, NULL);
|
||||
dbus_connection_set_watch_functions(conn->conn, add_watch, remove_watch, toggle_watch, conn,
|
||||
|
|
@ -375,7 +394,13 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
|
|||
|
||||
static int impl_clear(struct spa_handle *handle)
|
||||
{
|
||||
struct impl *impl = (struct impl *) handle;
|
||||
struct connection *conn;
|
||||
|
||||
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
||||
|
||||
spa_list_consume(conn, &impl->connection_list, link)
|
||||
connection_free(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue