From a5e96b9eb3a28d1ee1753bcc94d85ec4efa8c980 Mon Sep 17 00:00:00 2001 From: Tom Mulcahy Date: Thu, 7 May 2020 12:46:18 -0700 Subject: [PATCH] Retry extract_DT_NEEDED when interrupted Summary: FileChannel will throw ClosedByInterruptException if it's running within a thread that is interrupted. If that happens, we need to catch the exception and retry. If not the class load failure will get memoized and any future attempt to load the same class will also fail. Reviewed By: tophyr Differential Revision: D21438754 fbshipit-source-id: af914c83ca60a0572cc9a6b05ed35318b69795a1 --- java/com/facebook/soloader/MinElf.java | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/java/com/facebook/soloader/MinElf.java b/java/com/facebook/soloader/MinElf.java index 423e7a9..560428c 100644 --- a/java/com/facebook/soloader/MinElf.java +++ b/java/com/facebook/soloader/MinElf.java @@ -16,11 +16,13 @@ package com.facebook.soloader; +import android.util.Log; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.channels.ClosedByInterruptException; import java.nio.channels.FileChannel; /** @@ -32,6 +34,8 @@ */ public final class MinElf { + private static final String TAG = "MinElf"; + public static enum ISA { NOT_SO("not_so"), X86("x86"), @@ -65,10 +69,18 @@ public String toString() { public static String[] extract_DT_NEEDED(File elfFile) throws IOException { FileInputStream is = new FileInputStream(elfFile); - try { - return extract_DT_NEEDED(is.getChannel()); - } finally { - is.close(); // Won't throw + while (true) { + try { + return extract_DT_NEEDED(is.getChannel()); + } catch (ClosedByInterruptException e) { + // Some other thread interrupted us. We need to try again. This is + // especially important since this is often used within the context of + // a static initializer. A failure here will get memoized resulting in + // all future attempts to load the same class to fail. + Log.e(TAG, "retrying extract_DT_NEEDED due to ClosedByInterruptException", e); + } finally { + is.close(); // Won't throw + } } }