Set renderThreadHandler to null on uncaught exception in EglRenderer.

This should prevent us from posting and deadlocking if EglRenderer
thread crashes.

Bug: b/117400268
Change-Id: I978738249917cb5194917b0b2b12f67bb2a8642e
Reviewed-on: https://webrtc-review.googlesource.com/c/107043
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Paulina Hensman <phensman@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25271}
diff --git a/sdk/android/api/org/webrtc/EglRenderer.java b/sdk/android/api/org/webrtc/EglRenderer.java
index d0a1d98..bef34f5 100644
--- a/sdk/android/api/org/webrtc/EglRenderer.java
+++ b/sdk/android/api/org/webrtc/EglRenderer.java
@@ -17,6 +17,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Message;
 import android.view.Surface;
 import java.nio.ByteBuffer;
 import java.text.DecimalFormat;
@@ -79,6 +80,29 @@
     }
   }
 
+  /**
+   * Handler that triggers a callback when an uncaught exception happens when handling a message.
+   */
+  private static class HandlerWithExceptionCallback extends Handler {
+    private final Runnable exceptionCallback;
+
+    public HandlerWithExceptionCallback(Looper looper, Runnable exceptionCallback) {
+      super(looper);
+      this.exceptionCallback = exceptionCallback;
+    }
+
+    @Override
+    public void dispatchMessage(Message msg) {
+      try {
+        super.dispatchMessage(msg);
+      } catch (Exception e) {
+        Logging.e(TAG, "Exception on EglRenderer thread", e);
+        exceptionCallback.run();
+        throw e;
+      }
+    }
+  }
+
   protected final String name;
 
   // |renderThreadHandler| is a handler for communicating with |renderThread|, and is synchronized
@@ -174,7 +198,15 @@
 
       final HandlerThread renderThread = new HandlerThread(name + "EglRenderer");
       renderThread.start();
-      renderThreadHandler = new Handler(renderThread.getLooper());
+      renderThreadHandler =
+          new HandlerWithExceptionCallback(renderThread.getLooper(), new Runnable() {
+            @Override
+            public void run() {
+              synchronized (handlerLock) {
+                renderThreadHandler = null;
+              }
+            }
+          });
       // Create EGL context on the newly created render thread. It should be possibly to create the
       // context on this thread and make it current on the render thread, but this causes failure on
       // some Marvel based JB devices. https://bugs.chromium.org/p/webrtc/issues/detail?id=6350.