From d4f6f61a96a82a1a35c353b34287d2d819f9478b Mon Sep 17 00:00:00 2001 From: Nikhilesh Sigatapu Date: Mon, 9 May 2016 11:47:47 -0700 Subject: [PATCH] Increase the stack size for the React queue on older Android phones Summary: Older Android devices don't have a large stack by default and with about 16 levels of views the app will crash. Modern Android devices are fine so we can continue to use the system defaults while using a 2MB stack on older Android devices. Closes https://github.com/facebook/react-native/pull/7416 Differential Revision: D3276805 Pulled By: astreet fbshipit-source-id: a7b31a1be62e13f333148ca0908eb01a11aa4562 --- .../bridge/queue/MessageQueueThreadImpl.java | 26 +++++++++++++------ .../bridge/queue/MessageQueueThreadSpec.java | 17 ++++++++++++ .../queue/ReactQueueConfigurationSpec.java | 10 +++++-- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java index 5593cb02f7a..41a191faed8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java @@ -131,7 +131,7 @@ public class MessageQueueThreadImpl implements MessageQueueThread { case MAIN_UI: return createForMainThread(spec.getName(), exceptionHandler); case NEW_BACKGROUND: - return startNewBackgroundThread(spec.getName(), exceptionHandler); + return startNewBackgroundThread(spec.getName(), spec.getStackSize(), exceptionHandler); default: throw new RuntimeException("Unknown thread type: " + spec.getThreadType()); } @@ -165,17 +165,27 @@ public class MessageQueueThreadImpl implements MessageQueueThread { return mqt; } - /** - * Creates and starts a new MessageQueueThreadImpl encapsulating a new Thread with a new Looper - * running on it. Give it a name for easier debugging. When this method exits, the new - * MessageQueueThreadImpl is ready to receive events. - */ public static MessageQueueThreadImpl startNewBackgroundThread( final String name, QueueThreadExceptionHandler exceptionHandler) { + return startNewBackgroundThread( + name, + MessageQueueThreadSpec.DEFAULT_STACK_SIZE_BYTES, + exceptionHandler); + } + + /** + * Creates and starts a new MessageQueueThreadImpl encapsulating a new Thread with a new Looper + * running on it. Give it a name for easier debugging and optionally a suggested stack size. + * When this method exits, the new MessageQueueThreadImpl is ready to receive events. + */ + public static MessageQueueThreadImpl startNewBackgroundThread( + final String name, + long stackSize, + QueueThreadExceptionHandler exceptionHandler) { final SimpleSettableFuture looperFuture = new SimpleSettableFuture<>(); final SimpleSettableFuture mqtFuture = new SimpleSettableFuture<>(); - Thread bgThread = new Thread( + Thread bgThread = new Thread(null, new Runnable() { @Override public void run() { @@ -186,7 +196,7 @@ public class MessageQueueThreadImpl implements MessageQueueThread { Looper.loop(); } - }, "mqt_" + name); + }, "mqt_" + name, stackSize); bgThread.start(); Looper myLooper = looperFuture.getOrThrow(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadSpec.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadSpec.java index 89673016cad..1ff61fdf4e5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadSpec.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadSpec.java @@ -17,6 +17,9 @@ public class MessageQueueThreadSpec { private static final MessageQueueThreadSpec MAIN_UI_SPEC = new MessageQueueThreadSpec(ThreadType.MAIN_UI, "main_ui"); + // The Thread constructor interprets zero the same as not specifying a stack size + public static final long DEFAULT_STACK_SIZE_BYTES = 0; + protected static enum ThreadType { MAIN_UI, NEW_BACKGROUND, @@ -26,16 +29,26 @@ public class MessageQueueThreadSpec { return new MessageQueueThreadSpec(ThreadType.NEW_BACKGROUND, name); } + public static MessageQueueThreadSpec newBackgroundThreadSpec(String name, long stackSize) { + return new MessageQueueThreadSpec(ThreadType.NEW_BACKGROUND, name, stackSize); + } + public static MessageQueueThreadSpec mainThreadSpec() { return MAIN_UI_SPEC; } private final ThreadType mThreadType; private final String mName; + private final long mStackSize; private MessageQueueThreadSpec(ThreadType threadType, String name) { + this(threadType, name, DEFAULT_STACK_SIZE_BYTES); + } + + private MessageQueueThreadSpec(ThreadType threadType, String name, long stackSize) { mThreadType = threadType; mName = name; + mStackSize = stackSize; } public ThreadType getThreadType() { @@ -45,4 +58,8 @@ public class MessageQueueThreadSpec { public String getName() { return mName; } + + public long getStackSize() { + return mStackSize; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java index aceeba6aa9c..133504887a0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java @@ -9,6 +9,8 @@ package com.facebook.react.bridge.queue; +import android.os.Build; + import javax.annotation.Nullable; import com.facebook.infer.annotation.Assertions; @@ -21,6 +23,8 @@ import com.facebook.infer.annotation.Assertions; */ public class ReactQueueConfigurationSpec { + private static final long LEGACY_STACK_SIZE_BYTES = 2000000; + private final MessageQueueThreadSpec mNativeModulesQueueThreadSpec; private final MessageQueueThreadSpec mJSQueueThreadSpec; @@ -44,10 +48,12 @@ public class ReactQueueConfigurationSpec { } public static ReactQueueConfigurationSpec createDefault() { + MessageQueueThreadSpec spec = Build.VERSION.SDK_INT < 21 ? + MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules", LEGACY_STACK_SIZE_BYTES) : + MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules"); return builder() .setJSQueueThreadSpec(MessageQueueThreadSpec.newBackgroundThreadSpec("js")) - .setNativeModulesQueueThreadSpec( - MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules")) + .setNativeModulesQueueThreadSpec(spec) .build(); }