From 0f0d54e5c554266a35d259fc6b87c2b1b6d81849 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 8 Dec 2011 17:05:45 +0100 Subject: [PATCH] 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 --- compositor/compositor-drm.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c index 1f5e0289..2291f480 100644 --- a/compositor/compositor-drm.c +++ b/compositor/compositor-drm.c @@ -427,7 +427,7 @@ create_output_for_connector(struct drm_compositor *ec, 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 @@ create_output_for_connector(struct drm_compositor *ec, 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++) { + ret = drm_output_add_mode(output, &connector->modes[i]); + if (ret) + goto err_free; + } - 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); + 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 @@ create_output_for_connector(struct drm_compositor *ec, 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 @@ create_output_for_connector(struct drm_compositor *ec, 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