Increase time to set allocation limit.

Under some circumstances, it's possible to fail the enable allocation
limit android_mallopt call. Increase the total allowed time for the
function to complete.

In addition, if the enable fails, allow another limit call to succeed
in the future.

Finally, change the limit test to use _exit instead of exit.

Bug: 291672185

Test: Ran limit test thousands of times.
Test: Forced the limit to fail and verified the second call passes.
Change-Id: I0948e6fd97231a7538b9b82b76f0a207386681b1
diff --git a/libc/bionic/malloc_limit.cpp b/libc/bionic/malloc_limit.cpp
index 1405a39..deb63f4 100644
--- a/libc/bionic/malloc_limit.cpp
+++ b/libc/bionic/malloc_limit.cpp
@@ -278,7 +278,7 @@
   // being called, allow a short period for the signal handler to complete
   // before failing.
   bool enabled = false;
-  size_t num_tries = 20;
+  size_t num_tries = 200;
   while (true) {
     if (!atomic_exchange(&gGlobalsMutating, true)) {
       __libc_globals.mutate([](libc_globals* globals) {
@@ -328,9 +328,16 @@
     current_allocated = Malloc(mallinfo)().uordblks;
   }
 #endif
+  // This has to be set before the enable occurs since "gAllocated" is used
+  // to compute the limit. If the enable fails, "gAllocated" is never used.
   atomic_store(&gAllocated, current_allocated);
 
-  return EnableLimitDispatchTable();
+  if (!EnableLimitDispatchTable()) {
+    // Failed to enable, reset so a future enable will pass.
+    atomic_store(&limit_enabled, false);
+    return false;
+  }
+  return true;
 }
 
 static size_t LimitUsableSize(const void* mem) {
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 2dbc680..776643d 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1384,7 +1384,7 @@
     threads[i]->join();
   }
   ASSERT_EQ(1U, num_successful) << "Only one thread should be able to set the limit.";
-  exit(0);
+  _exit(0);
 }
 #endif