compositor-drm: Free output on error in create_output_for_connector
We currently simply return -1 on error in create_output_for_connector. This
correctly frees the output and all modes when we fail to avoid memory leaks.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c
index 1f5e028..2291f48 100644
--- a/compositor/compositor-drm.c
+++ b/compositor/compositor-drm.c
@@ -427,7 +427,7 @@
int x, int y)
{
struct drm_output *output;
- struct drm_mode *drm_mode;
+ struct drm_mode *drm_mode, *next;
drmModeEncoder *encoder;
int i, ret;
unsigned handle, stride;
@@ -467,11 +467,19 @@
ec->connector_allocator |= (1 << output->connector_id);
output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
+ drmModeFreeEncoder(encoder);
- for (i = 0; i < connector->count_modes; i++)
- drm_output_add_mode(output, &connector->modes[i]);
- if (connector->count_modes == 0)
- drm_output_add_mode(output, &builtin_1024x768);
+ for (i = 0; i < connector->count_modes; i++) {
+ ret = drm_output_add_mode(output, &connector->modes[i]);
+ if (ret)
+ goto err_free;
+ }
+
+ if (connector->count_modes == 0) {
+ ret = drm_output_add_mode(output, &builtin_1024x768);
+ if (ret)
+ goto err_free;
+ }
drm_mode = container_of(output->base.mode_list.next,
struct drm_mode, base.link);
@@ -479,8 +487,6 @@
drm_mode->base.flags =
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
- drmModeFreeEncoder(encoder);
-
glGenRenderbuffers(2, output->rbo);
for (i = 0; i < 2; i++) {
glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]);
@@ -541,6 +547,20 @@
output->base.destroy = drm_output_destroy;
return 0;
+
+err_free:
+ wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
+ base.link) {
+ wl_list_remove(&drm_mode->base.link);
+ free(drm_mode);
+ }
+
+ drmModeFreeCrtc(output->original_crtc);
+ ec->crtc_allocator &= ~(1 << output->crtc_id);
+ ec->connector_allocator &= ~(1 << output->connector_id);
+
+ free(output);
+ return -1;
}
static int