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;
 }