pipewire: handle allocation failures

And make sure we don't leak things in the error paths.
This commit is contained in:
Wim Taymans 2026-05-05 14:44:39 +02:00
parent 67e8da3390
commit 2ac7c81958
3 changed files with 36 additions and 18 deletions

View file

@ -85,6 +85,19 @@ static int do_stop(struct spa_loop *loop, bool async, uint32_t seq,
return 0;
}
static void data_loop_free(struct pw_data_loop *loop)
{
if (loop->loop && loop->created)
pw_loop_destroy(loop->loop);
spa_hook_list_clean(&loop->listener_list);
free(loop->affinity);
free(loop->class);
pw_free_strv(loop->classes);
free(loop);
}
static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict *props)
{
struct pw_data_loop *this;
@ -98,6 +111,7 @@ static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict
}
pw_log_debug("%p: new", this);
spa_hook_list_init(&this->listener_list);
if (loop == NULL) {
loop = pw_loop_new(props);
@ -142,14 +156,17 @@ static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict
goto error_free;
}
this->classes = pw_strv_parse(class, strlen(class), INT_MAX, NULL);
if (this->classes == NULL) {
res = -ENOMEM;
goto error_free;
}
if (!this->loop->name[0])
pw_loop_set_name(this->loop, name);
spa_hook_list_init(&this->listener_list);
return this;
error_free:
free(this);
data_loop_free(this);
error_cleanup:
errno = -res;
return NULL;
@ -165,7 +182,6 @@ struct pw_data_loop *pw_data_loop_new(const struct spa_dict *props)
return loop_new(NULL, props);
}
/** Destroy a data loop
* \param loop the data loop to destroy
*/
@ -178,15 +194,7 @@ void pw_data_loop_destroy(struct pw_data_loop *loop)
pw_data_loop_stop(loop);
if (loop->created)
pw_loop_destroy(loop->loop);
spa_hook_list_clean(&loop->listener_list);
free(loop->affinity);
free(loop->class);
pw_free_strv(loop->classes);
free(loop);
data_loop_free(loop);
}
SPA_EXPORT

View file

@ -216,12 +216,15 @@ pw_context_load_module(struct pw_context *context,
pw_properties_set(this->properties, PW_KEY_MODULE_NAME, name);
spa_list_prepend(&context->module_list, &this->link);
this->info.name = name ? strdup(name) : NULL;
this->info.filename = filename;
filename = NULL;
this->info.filename = spa_steal_ptr(filename);
this->info.args = args ? strdup(args) : NULL;
spa_list_prepend(&context->module_list, &this->link);
if ((name != NULL && this->info.name == NULL) ||
(args != NULL && this->info.args == NULL))
goto error_strdup_fail;
this->global = pw_global_new(context,
PW_TYPE_INTERFACE_Module,
@ -272,6 +275,9 @@ error_no_mem:
res = -errno;
pw_log_error("can't allocate module: %m");
goto error_close;
error_strdup_fail:
res = -errno;
goto error_free_module;
error_no_global:
res = -errno;
pw_log_error("\"%s\": failed to create global: %m", this->info.filename);

View file

@ -1580,11 +1580,11 @@ stream_new(struct pw_context *context, const char *name,
this = &impl->this;
pw_log_debug("%p: new \"%s\"", impl, name);
if (props == NULL) {
if (props == NULL)
props = pw_properties_new(PW_KEY_MEDIA_NAME, name, NULL);
} else if (pw_properties_get(props, PW_KEY_MEDIA_NAME) == NULL) {
else if (pw_properties_get(props, PW_KEY_MEDIA_NAME) == NULL)
pw_properties_set(props, PW_KEY_MEDIA_NAME, name);
}
if (props == NULL) {
res = -errno;
goto error_properties;
@ -1610,6 +1610,10 @@ stream_new(struct pw_context *context, const char *name,
pw_context_conf_update_props(context, "stream.properties", props);
this->name = name ? strdup(name) : NULL;
if (name != NULL && this->name == NULL) {
res = -errno;
goto error_properties;
}
this->node_id = SPA_ID_INVALID;
spa_ringbuffer_init(&impl->dequeued.ring);