summaryrefslogblamecommitdiff
path: root/system/ruby/fix-get_main_stack.patch
blob: 4bb9a0932490e8e0d32a28190d1d40e877cbcc5c (plain) (tree)




































































                                                                                   
diff --git a/thread_pthread.c b/thread_pthread.c
index 951885ffa0..cf90321d1d 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -530,9 +530,6 @@ hpux_attr_getstackaddr(const pthread_attr_t *attr, void **addr)
 #   define MAINSTACKADDR_AVAILABLE 0
 # endif
 #endif
-#if MAINSTACKADDR_AVAILABLE && !defined(get_main_stack)
-# define get_main_stack(addr, size) get_stack(addr, size)
-#endif
 
 #ifdef STACKADDR_AVAILABLE
 /*
@@ -614,6 +611,55 @@ get_stack(void **addr, size_t *size)
     return 0;
 #undef CHECK_ERR
 }
+
+#if defined(__linux__) && !defined(__GLIBC__) && defined(HAVE_GETRLIMIT)
+
+#ifndef PAGE_SIZE
+#include <unistd.h>
+#define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
+#endif
+
+static int
+get_main_stack(void **addr, size_t *size)
+{
+    size_t start, end, limit, prevend = 0;
+    struct rlimit r;
+    FILE *f;
+    char buf[PATH_MAX+80], s[8];
+    int n;
+    STACK_GROW_DIR_DETECTION;
+
+    f = fopen("/proc/self/maps", "re");
+    if (!f)
+        return -1;
+    n = 0;
+    while (fgets(buf, sizeof buf, f)) {
+        n = sscanf(buf, "%zx-%zx %*s %*s %*s %*s %7s", &start, &end, s);
+        if (n >= 2) {
+            if (n == 3 && strcmp(s, "[stack]") == 0)
+                break;
+            prevend = end;
+        }
+        n = 0;
+    }
+    fclose(f);
+    if (n == 0)
+        return -1;
+
+    limit = 100 << 20; /* 100MB stack limit */
+    if (getrlimit(RLIMIT_STACK, &r)==0 && r.rlim_cur < limit)
+        limit = r.rlim_cur & -PAGE_SIZE;
+    if (limit > end) limit = end;
+    if (prevend < end - limit) prevend = end - limit;
+    if (start > prevend) start = prevend;
+    *addr = IS_STACK_DIR_UPPER() ? (void *)start : (void *)end;
+    *size = end - start;
+    return 0;
+}
+#else
+# define get_main_stack(addr, size) get_stack(addr, size)
+#endif
+
 #endif
 
 static struct {