From d0af5c6fd46d9248113a4c5f0e0fc54c9671b394 Mon Sep 17 00:00:00 2001 From: sakal Date: Tue, 25 Oct 2016 07:20:52 -0700 Subject: [PATCH] Fix a deadlock in EglRenderer.releaseEglSurface. Main thread is waiting for an operation on the render thread to complete while holding the handler lock. Something can be waiting on the render thread for this lock. This CL changes the behaviour so that the lock is released before waiting for the operation to complete. BUG=webrtc:6602,webrtc:6470 R=magjed@webrtc.org Review-Url: https://codereview.webrtc.org/2449693003 Cr-Commit-Position: refs/heads/master@{#14773} --- webrtc/api/android/java/src/org/webrtc/EglRenderer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/webrtc/api/android/java/src/org/webrtc/EglRenderer.java b/webrtc/api/android/java/src/org/webrtc/EglRenderer.java index 415e127854..d5c29e7740 100644 --- a/webrtc/api/android/java/src/org/webrtc/EglRenderer.java +++ b/webrtc/api/android/java/src/org/webrtc/EglRenderer.java @@ -380,23 +380,28 @@ public class EglRenderer implements VideoRenderer.Callbacks { * Release EGL surface. This function will block until the EGL surface is released. */ public void releaseEglSurface() { + final CountDownLatch completionLatch = new CountDownLatch(1); // Ensure that the render thread is no longer touching the Surface before returning from this // function. eglSurfaceCreationRunnable.setSurface(null /* surface */); synchronized (handlerLock) { if (renderThreadHandler != null) { renderThreadHandler.removeCallbacks(eglSurfaceCreationRunnable); - ThreadUtils.invokeAtFrontUninterruptibly(renderThreadHandler, new Runnable() { + renderThreadHandler.postAtFrontOfQueue(new Runnable() { @Override public void run() { if (eglBase != null) { eglBase.detachCurrent(); eglBase.releaseSurface(); } + completionLatch.countDown(); } }); + } else { + completionLatch.countDown(); } } + ThreadUtils.awaitUninterruptibly(completionLatch); } /**