[android] Add fallback for thread bounds calculation for Android.
authorRodrigo Kumpera <kumpera@gmail.com>
Mon, 16 Nov 2015 05:22:56 +0000 (00:22 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Mon, 28 Mar 2016 19:47:38 +0000 (12:47 -0700)
On some junk Samsung x86 device, pthread_attr_getstack is completely broken.

If the returned value is not sane, we parse /proc/self/maps to find the right
memory regions for the current stack.

Fixes BXC #21550 and DESK #83333.

List of original contributors:

Rodrigo Kumpera <kumpera@gmail.com>

mono/utils/mono-threads-android.c

index a72ee81a56075a5d45a8c36fa2ae5a356b2c9171..fa82387f26ff8e01f26dfc12874eeea0a91d56ab 100644 (file)
@@ -2,8 +2,55 @@
 
 #if defined(PLATFORM_ANDROID)
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/mono-threads-android.c"
-#endif
+#include <pthread.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include "glib.h"
+
+static void
+slow_get_thread_bounds (guint8 *current, guint8 **staddr, size_t *stsize)
+{
+       char buff [1024];
+       FILE *f = fopen ("/proc/self/maps", "r");
+       if (!f)
+               g_error ("Could not determine thread bounds, failed to open /proc/self/maps");
+
+       while (fgets (buff, sizeof (buff), f)) {
+               intmax_t low, high;
+               char *ptr = buff;
+               char *end = NULL;
+               //each line starts with the range we want: f7648000-f7709000
+               low = strtoimax (ptr, &end, 16);
+               if (end) {
+                       ptr = end + 1; //skip the dash to make sure we don't get a negative number
+                       end = NULL;
+                       high = strtoimax (ptr, &end, 16);
+               }
+               if (end && low <= (intmax_t)(size_t)current && high > (intmax_t)(size_t)current) {
+                       *staddr = (guint8 *)(size_t)low;
+                       *stsize = (size_t)(high - low);
+                       fclose (f);
+                       return;
+               }
+       }
+       g_error ("Could not determine thread bounds, failed to find current stack pointer in /proc/self/maps");
+}
+
+void
+mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize)
+{
+       pthread_attr_t attr;
+       guint8 *current = (guint8*)&attr;
+
+       *staddr = NULL;
+       *stsize = (size_t)-1;
+
+       pthread_getattr_np (pthread_self (), &attr);
+       pthread_attr_getstack (&attr, (void**)staddr, stsize);
+       pthread_attr_destroy (&attr);
+
+       if (*staddr && ((current <= *staddr) || (current > *staddr + *stsize)))
+               slow_get_thread_bounds (current, staddr, stsize);
+}
 
 #endif