ART: Flag to fail thread creation

Add a flag to mark when the zygote is not allowed to create threads.

Bug: 27248115
Bug: 28149511

(cherry picked from commit 415d8070e37c20dfb7e6dc37e74fdb5fffc2022e)

Change-Id: I1dc3620d9e7d0054c672b993d89459fc4b353dfc
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 887eee0..1aa789f 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -209,9 +209,21 @@
   }
 }
 
+static void ZygoteHooks_startZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,
+                                                    jclass klass ATTRIBUTE_UNUSED) {
+  Runtime::Current()->SetZygoteNoThreadSection(true);
+}
+
+static void ZygoteHooks_stopZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,
+                                                   jclass klass ATTRIBUTE_UNUSED) {
+  Runtime::Current()->SetZygoteNoThreadSection(false);
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"),
   NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JIZLjava/lang/String;)V"),
+  NATIVE_METHOD(ZygoteHooks, startZygoteNoThreadCreation, "()V"),
+  NATIVE_METHOD(ZygoteHooks, stopZygoteNoThreadCreation, "()V"),
 };
 
 void register_dalvik_system_ZygoteHooks(JNIEnv* env) {
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index 13edd67..a742e81 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -47,6 +47,15 @@
 
 static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
                                 jboolean daemon) {
+  // There are sections in the zygote that forbid thread creation.
+  Runtime* runtime = Runtime::Current();
+  if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {
+    jclass internal_error = env->FindClass("java/lang/InternalError");
+    CHECK(internal_error != nullptr);
+    env->ThrowNew(internal_error, "Cannot create threads in zygote");
+    return;
+  }
+
   Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);
 }
 
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index d3454e8..0a65b6b 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -204,6 +204,7 @@
       implicit_so_checks_(false),
       implicit_suspend_checks_(false),
       no_sig_chain_(false),
+      force_native_bridge_(false),
       is_native_bridge_loaded_(false),
       is_native_debuggable_(false),
       zygote_max_failed_boots_(0),
@@ -211,9 +212,11 @@
       oat_file_manager_(nullptr),
       is_low_memory_mode_(false),
       safe_mode_(false),
+      dump_native_stack_on_sig_quit_(true),
       pruned_dalvik_cache_(false),
       // Initially assume we perceive jank in case the process state is never updated.
-      process_state_(kProcessStateJankPerceptible) {
+      process_state_(kProcessStateJankPerceptible),
+      zygote_no_threads_(false) {
   CheckAsmSupportOffsetsAndSizes();
   std::fill(callee_save_methods_, callee_save_methods_ + arraysize(callee_save_methods_), 0u);
   interpreter::CheckInterpreterAsmConstants();
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 6a6fdb7..ae25dd1 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -635,6 +635,14 @@
     return process_state_ == kProcessStateJankPerceptible;
   }
 
+  void SetZygoteNoThreadSection(bool val) {
+    zygote_no_threads_ = val;
+  }
+
+  bool IsZygoteNoThreadSection() const {
+    return zygote_no_threads_;
+  }
+
  private:
   static void InitPlatformSignalHandlers();
 
@@ -856,6 +864,9 @@
   // Whether or not we currently care about pause times.
   ProcessState process_state_;
 
+  // Whether zygote code is in a section that should not start threads.
+  bool zygote_no_threads_;
+
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };
 std::ostream& operator<<(std::ostream& os, const Runtime::CalleeSaveType& rhs);