drm_hwcomposer: Fix fence leak
Hwcomposer is responsible for closing the acquire fences passed
in during hwc_set. Make sure that it does so, even if there is
an error condition.
Change-Id: I5c9096804c2613ec317c306dd361cb5f1a2ba5b2
Signed-off-by: Lauri Peltonen <lpeltonen@nvidia.com>
Reviewed-on: https://chrome-internal-review.googlesource.com/198356
Tested-by: Stéphane Marchesin <marcheu@google.com>
Commit-Queue: Stéphane Marchesin <marcheu@google.com>
Reviewed-by: Stéphane Marchesin <marcheu@google.com>
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 2fe2244..cf0a8c3 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -279,6 +279,16 @@
struct drm_gem_close args;
int ret, i;
+ if (buf->acquire_fence_fd >= 0) {
+ ret = sync_wait(buf->acquire_fence_fd, -1);
+ close(buf->acquire_fence_fd);
+ buf->acquire_fence_fd = -1;
+ if (ret) {
+ ALOGE("Failed to wait for acquire %d", ret);
+ return ret;
+ }
+ }
+
ret = drmModeAddFB2(hd->ctx->fd, buf->width,
buf->height, buf->format, buf->gem_handles, buf->pitches,
buf->offsets, &buf->fb_id, 0);
@@ -287,14 +297,6 @@
return ret;
}
- if (buf->acquire_fence_fd >= 0) {
- ret = sync_wait(buf->acquire_fence_fd, -1);
- if (ret) {
- ALOGE("Failed to wait for acquire %d", ret);
- return ret;
- }
- }
-
ret = hwc_flip(hd, buf);
if (ret) {
ALOGE("Failed to perform flip\n");
@@ -388,11 +390,12 @@
ret = hwc_get_drm_display(ctx, display, &hd);
if (ret)
- return ret;
+ goto out;
if (!hd->active_crtc) {
ALOGE("There is no active crtc for display %d", display);
- return -ENOENT;
+ ret = -ENOENT;
+ goto out;
}
/*
@@ -419,14 +422,15 @@
&buf);
if (ret) {
ALOGE("Failed to import handle to drm bo %d", ret);
- return ret;
+ goto out;
}
buf.acquire_fence_fd = layer->acquireFenceFd;
+ layer->acquireFenceFd = -1;
ret = pthread_mutex_lock(&hd->set_worker.lock);
if (ret) {
ALOGE("Failed to lock set lock in set() %d", ret);
- return ret;
+ goto out;
}
/*
@@ -442,22 +446,25 @@
hd->buf_queue.push(buf);
ret = pthread_cond_signal(&hd->set_worker.cond);
- if (ret) {
+ if (ret)
ALOGE("Failed to signal set worker %d", ret);
- goto out;
- }
- ret = pthread_mutex_unlock(&hd->set_worker.lock);
- if (ret) {
- ALOGE("Failed to unlock set lock in set() %d", ret);
- return ret;
- }
-
- return ret;
+ if (pthread_mutex_unlock(&hd->set_worker.lock))
+ ALOGE("Failed to unlock set lock in set()");
out:
- if (pthread_mutex_unlock(&hd->set_worker.lock))
- ALOGE("Failed to unlock set lock in set error handler");
+ /* Close input fences. */
+ for (i = 0; i < (int)display_contents->numHwLayers; i++) {
+ layer = &display_contents->hwLayers[i];
+ if (layer->acquireFenceFd >= 0) {
+ close(layer->acquireFenceFd);
+ layer->acquireFenceFd = -1;
+ }
+ }
+ if (display_contents->outbufAcquireFenceFd >= 0) {
+ close(display_contents->outbufAcquireFenceFd);
+ display_contents->outbufAcquireFenceFd = -1;
+ }
return ret;
}