am fd955033: Merge "pthread: Invalidate stale stack pointers on pthread_exit()"

* commit 'fd95503347acba5c52d669a186ad2b161338a8a7':
  pthread: Invalidate stale stack pointers on pthread_exit()
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 73e4a64..2e2c09d 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -577,6 +577,17 @@
         _pthread_internal_remove(thread);
         _pthread_internal_free(thread);
     } else {
+        pthread_mutex_lock(&gThreadListLock);
+
+       /* make sure that the thread struct doesn't have stale pointers to a stack that
+        * will be unmapped after the exit call below.
+        */
+        if (!user_stack) {
+            thread->attr.stack_base = NULL;
+            thread->attr.stack_size = 0;
+            thread->tls = NULL;
+        }
+
        /* the join_count field is used to store the number of threads waiting for
         * the termination of this thread with pthread_join(),
         *
@@ -589,7 +600,6 @@
         * is gone (as well as its TLS area). when another thread calls pthread_join()
         * on it, it will immediately free the thread and return.
         */
-        pthread_mutex_lock(&gThreadListLock);
         thread->return_value = retval;
         if (thread->join_count > 0) {
             pthread_cond_broadcast(&thread->join_cond);
@@ -1942,7 +1952,9 @@
          * similarly, it is possible to have thr->tls == NULL for threads that
          * were just recently created through pthread_create() but whose
          * startup trampoline (__thread_entry) hasn't been run yet by the
-         * scheduler. so check for this too.
+         * scheduler. thr->tls will also be NULL after it's stack has been
+         * unmapped but before the ongoing pthread_join() is finished.
+         * so check for this too.
          */
         if (thr->join_count < 0 || !thr->tls)
             continue;