aboutsummaryrefslogtreecommitdiffstats
path: root/lang/ruby18
diff options
context:
space:
mode:
authorstas <stas@FreeBSD.org>2009-10-12 21:15:50 +0800
committerstas <stas@FreeBSD.org>2009-10-12 21:15:50 +0800
commit45ee131efaa8d1c5e030f8e52c9fcaa51157d275 (patch)
tree3e4f66053c75cf333a213df6572c4262de560e1c /lang/ruby18
parent5e432d2cc4d2793c8246d77256f0b6fb85064dde (diff)
downloadfreebsd-ports-gnome-45ee131efaa8d1c5e030f8e52c9fcaa51157d275.tar.gz
freebsd-ports-gnome-45ee131efaa8d1c5e030f8e52c9fcaa51157d275.tar.zst
freebsd-ports-gnome-45ee131efaa8d1c5e030f8e52c9fcaa51157d275.zip
- Don't build ruby with threads support on FreeBSD versions before 7.2
- On FreeBSD >= 7.2 allocate the new thread with adequate amount of stack space to run the main ruby code in. This allows to mitigate problem when too low stack space available for ruby when running with pthreads enabled. - Bump portrevision. The long version. Before this change we used to link ruby against pthreads uncoditionally on all versions of FreeBSD. This is indispensable in order to load the threaded shared objects withing ruby. However, this causes a dramatic decrease in the stack space available as pthreads only allows up to several megabytes of stack space for the main application threads. The only solution to this is to create the new thread immediately after the program start with rigth stack size attributes set. Nonetheless this scheme won't work for us on FreeBSD version before 7.2 as malloc implementation in these versions was not threaded fork safe (i.e. this is impossible to fork from the threaded program and expect malloc/free functions to work). Thus the only solution for now can be to disable pthreads entirely on FreeBSD <= 7.2. This won't cause any performance/usability problems for users as Ruby 1.8 uses green threads, however it may prevent <= 7.2 users to load shared libraries linked agains pthreads. Reported by: "François Montel" <seanmullen@gmail.com> Tested by: Sean Mullen <seanmullen@gmail.com>
Diffstat (limited to 'lang/ruby18')
-rw-r--r--lang/ruby18/Makefile7
-rw-r--r--lang/ruby18/files/patch-gc.c75
-rw-r--r--lang/ruby18/files/patch-main.c86
3 files changed, 150 insertions, 18 deletions
diff --git a/lang/ruby18/Makefile b/lang/ruby18/Makefile
index 5ab744a3f44f..9d175d627ee7 100644
--- a/lang/ruby18/Makefile
+++ b/lang/ruby18/Makefile
@@ -56,6 +56,13 @@ _SUF1= _${PORTREVISION}
PKGNAMESUFFIX= #empty
+#
+# pthreads in earlier versions has problems with malloc after fork
+#
+.if ${OSVERSION} < 702000
+WITHOUT_PTHREADS= yes
+.endif
+
.if defined(WITHOUT_PTHREADS)
CONFIGURE_ARGS+=--disable-pthread
PKGNAMESUFFIX:= ${PKGNAMESUFFIX}+nopthreads
diff --git a/lang/ruby18/files/patch-gc.c b/lang/ruby18/files/patch-gc.c
index 873c96c76908..2ca3a480416f 100644
--- a/lang/ruby18/files/patch-gc.c
+++ b/lang/ruby18/files/patch-gc.c
@@ -1,5 +1,5 @@
--- gc.c.orig 2009-03-27 13:25:23.000000000 +0300
-+++ gc.c 2009-06-19 16:26:54.000000000 +0400
++++ gc.c 2009-09-29 01:09:29.000000000 +0400
@@ -30,6 +30,10 @@
#include <sys/resource.h>
#endif
@@ -19,7 +19,16 @@
int ruby_gc_stress = 0;
-@@ -534,9 +539,14 @@
+@@ -485,6 +490,8 @@
+ # define STACK_LEVEL_MAX 655300
+ #endif
+
++VALUE *stack_bottom_addr = 0x0;
++
+ #ifdef C_ALLOCA
+ # define SET_STACK_END VALUE stack_end; alloca(0);
+ # define STACK_END (&stack_end)
+@@ -534,9 +541,22 @@
#define GC_WATER_MARK 512
@@ -27,27 +36,35 @@
+#define CHECK_STACK(ret, prev) do {\
SET_STACK_END;\
- (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
-+ ssize_t avail = STACK_LEVEL_MAX + GC_WATER_MARK - STACK_LENGTH;\
-+ if (avail <= 0 || (prev != -1 && (signed)(STACK_LENGTH - prev) > avail))\
++ ssize_t avail;\
++ if (stack_bottom_addr != 0) {\
++ if (STACK_UPPER(&avail, 1, -1) > 0)\
++ avail = stack_bottom_addr - STACK_END;\
++ else\
++ avail = STACK_END - stack_bottom_addr;\
++ } else {\
++ avail = STACK_LEVEL_MAX + GC_WATER_MARK - STACK_LENGTH;\
++ }\
++ if (avail <= 0 || (prev != 0 && (prev - avail) > avail))\
+ (ret) = 1;\
+ else\
+ (ret) = 0;\
-+ (prev) = STACK_LENGTH;\
++ (prev) = avail;\
} while (0)
size_t
-@@ -552,8 +562,9 @@
+@@ -552,8 +572,9 @@
ruby_stack_check()
{
int ret;
-+ static size_t prev = -1;
++ static ssize_t prev = 0;
- CHECK_STACK(ret);
+ CHECK_STACK(ret, prev);
return ret;
}
-@@ -1599,18 +1610,50 @@
+@@ -1599,18 +1620,72 @@
}
rb_gc_stack_start = addr;
#endif
@@ -70,7 +87,9 @@
+#elif defined _WIN32
+ {
+ MEMORY_BASIC_INFORMATION mi;
-+
+
+- if (space > 1024*1024) space = 1024*1024;
+- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
+ if (VirtualQuery(&mi, &mi, sizeof(mi))) {
+ stacksize = (char *)mi.BaseAddress - (char *)mi.AllocationBase;
+ }
@@ -80,29 +99,49 @@
+ {
+ pthread_attr_t attr;
+ size_t size;
-
-- if (space > 1024*1024) space = 1024*1024;
-- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
++ void *addr;
++
+ pthread_attr_init(&attr);
+ if (pthread_attr_get_np(pthread_self(), &attr) == 0) {
-+ pthread_attr_getstacksize(&attr, &size);
++ pthread_attr_getstack(&attr, &addr, &size);
+ if (stacksize == 0 || size < stacksize)
+ stacksize = size;
- }
++ stack_bottom_addr = addr;
++ }
+ pthread_attr_destroy(&attr);
- }
- #endif
++ }
++#endif
+ if (stacksize) {
+ unsigned int space = stacksize / 5;
+
+ if (space > 1024*1024)
+ space = 1024*1024;
+ STACK_LEVEL_MAX = (stacksize - space) / sizeof(VALUE);
++#if defined(__FreeBSD__)
++#include <sys/sysctl.h>
++ if (stack_bottom_addr == 0) {
++ size_t len;
++ void *usrstack;
++ int mib[2];
++ int error;
++
++ len = sizeof(usrstack);
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_USRSTACK;
++ error = sysctl(mib, 2, &usrstack, &len, NULL, 0);
++ if (error == 0) {
++ if (STACK_UPPER(&avail, 1, -1) > 0)
++ stack_bottom_addr = usrstack + (stacksize - space);
++ else
++ stack_bottom_addr = usrstack - (stacksize - space);
+ }
+ }
+ #endif
+ }
}
void ruby_init_stack(VALUE *addr
-@@ -1631,31 +1674,7 @@
+@@ -1631,31 +1706,7 @@
rb_gc_register_stack_start = (VALUE*)bsp;
}
#endif
@@ -135,7 +174,7 @@
}
/*
-@@ -1980,7 +1999,7 @@
+@@ -1980,7 +2031,7 @@
chain_finalized_object(st_data_t key, st_data_t val, st_data_t arg)
{
RVALUE *p = (RVALUE *)key, **final_list = (RVALUE **)arg;
diff --git a/lang/ruby18/files/patch-main.c b/lang/ruby18/files/patch-main.c
new file mode 100644
index 000000000000..2fe3acb6c778
--- /dev/null
+++ b/lang/ruby18/files/patch-main.c
@@ -0,0 +1,86 @@
+--- main.c.orig 2007-02-13 02:01:19.000000000 +0300
++++ main.c 2009-09-28 15:55:36.000000000 +0400
+@@ -29,10 +29,21 @@
+ static void objcdummyfunction( void ) { objc_msgSend(); }
+ #endif
+
++#if defined(__FreeBSD__) && defined(_THREAD_SAFE)
++static int argc;
++static char **argv;
++static char **envp;
++#endif
++
++#if defined(__FreeBSD__) && defined(_THREAD_SAFE)
++void *
++main_entry(void *arg)
++#else
+ int
+ main(argc, argv, envp)
+ int argc;
+ char **argv, **envp;
++#endif
+ {
+ #ifdef _WIN32
+ NtInitialize(&argc, &argv);
+@@ -47,5 +58,61 @@
+ ruby_options(argc, argv);
+ ruby_run();
+ }
++#if defined(__FreeBSD__) && defined(_THREAD_SAFE)
++ return (NULL);
++#else
+ return 0;
++#endif
+ }
++
++#if defined(__FreeBSD__) && defined(_THREAD_SAFE)
++#include <sys/types.h>
++#include <sys/time.h>
++#include <sys/resource.h>
++int
++main(main_argc, main_argv, main_envp)
++ int main_argc;
++ char **main_argv, **main_envp;
++{
++ struct rlimit rl;
++ pthread_attr_t attr;
++ pthread_t tid;
++ size_t stacksize;
++ int error;
++
++ argc = main_argc;
++ argv = main_argv;
++ envp = main_envp;
++ /* Get the system imposed limit. */
++ error = getrlimit(RLIMIT_STACK, &rl);
++ if (error != 0) {
++ fprintf(stderr, "cannot obtain resource limit\n");
++ exit(1);
++ }
++ stacksize = rl.rlim_cur * 3 / 4; /* Set initial size to 3/4 of limit */
++ error = pthread_attr_init(&attr);
++ if (error != 0) {
++ fprintf(stderr, "cannot initialize thread attributes\n");
++ exit(1);
++ }
++ while (stacksize > 0) {
++ error = pthread_attr_setstacksize(&attr, stacksize);
++ if (error != 0)
++ goto next;
++ error = pthread_create(&tid, &attr, &main_entry, NULL);
++ if (error == 0)
++ break;
++ next:
++ stacksize = stacksize >> 1;
++ }
++ if (stacksize != 0) { /* Success. */
++ pthread_detach(tid);
++ pthread_exit(NULL);
++ return (0);
++ }
++ else {
++ fprintf(stderr, "Cannot create main thread\n");
++ return (1);
++ }
++}
++#endif