From 5cc78499fe78bb9013ec5f639b0c279e696f91fb Mon Sep 17 00:00:00 2001 From: q66 Date: Fri, 21 Feb 2020 03:24:42 +0100 Subject: [PATCH] ruby: fix crashes on musl + never use precompiled native gems on musl --- ...ubygems-avoid-platform-specific-gems.patch | 31 ++++++++ .../patches/musl-fix-get_main_stack.patch | 74 +++++++++++++++++++ .../test_insns-lower-recursion-depth.patch | 49 ++++++++++++ srcpkgs/ruby/template | 9 ++- 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/ruby/files/rubygems-avoid-platform-specific-gems.patch create mode 100644 srcpkgs/ruby/patches/musl-fix-get_main_stack.patch create mode 100644 srcpkgs/ruby/patches/test_insns-lower-recursion-depth.patch diff --git a/srcpkgs/ruby/files/rubygems-avoid-platform-specific-gems.patch b/srcpkgs/ruby/files/rubygems-avoid-platform-specific-gems.patch new file mode 100644 index 00000000000..da6884d090d --- /dev/null +++ b/srcpkgs/ruby/files/rubygems-avoid-platform-specific-gems.patch @@ -0,0 +1,31 @@ +From: Jakub Jirutka +Date: Fri, 19 May 2017 19:56:00 +0200 +Subject: [PATCH] Rubygems: don't install platform-specific gems + +Gems with native extensions typically contain just source code that is +built during installation on user's system. However, Rubygems allows to +publish even platform-specific gems with prebuilt binaries for specific +platform. The problem is that Rubygems uses only short platform +identification like x86_64-linux; it does not identify used libc. +And sadly platform-specific gems for linux are built against glibc, so +they may not work on musl libc. + +This patch is a workaround for the aforesaid problem. It removes local +platform from Rubygems' supported platforms to force it always pick +a platform-agnostic (source) gem. Users can override it using +`--platform` option. + +--- a/lib/rubygems.rb ++++ b/lib/rubygems.rb +@@ -764,7 +764,10 @@ + def self.platforms + @platforms ||= [] + if @platforms.empty? +- @platforms = [Gem::Platform::RUBY, Gem::Platform.local] ++ # XXX: Patched to avoid installing platform-specific gems with binaries ++ # linked against glibc. ++ @platforms = [Gem::Platform::RUBY] ++ #@platforms = [Gem::Platform::RUBY, Gem::Platform.local] + end + @platforms + end diff --git a/srcpkgs/ruby/patches/musl-fix-get_main_stack.patch b/srcpkgs/ruby/patches/musl-fix-get_main_stack.patch new file mode 100644 index 00000000000..e5edbbe2ad4 --- /dev/null +++ b/srcpkgs/ruby/patches/musl-fix-get_main_stack.patch @@ -0,0 +1,74 @@ +Source: Adélie Linux + +Fixes crashes on some musl platforms. + +diff --git a/thread_pthread.c b/thread_pthread.c +index 951885ffa0..cf90321d1d 100644 +--- thread_pthread.c ++++ thread_pthread.c +@@ -552,9 +552,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 + /* +@@ -632,6 +629,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 ++#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 { diff --git a/srcpkgs/ruby/patches/test_insns-lower-recursion-depth.patch b/srcpkgs/ruby/patches/test_insns-lower-recursion-depth.patch new file mode 100644 index 00000000000..db9d8bf04ad --- /dev/null +++ b/srcpkgs/ruby/patches/test_insns-lower-recursion-depth.patch @@ -0,0 +1,49 @@ +Source: Adélie Linux + +The patched test is a recursion function. We have lower stack size, +so we hit SystemStackError sooner than on other platforms. + + #361 test_insns.rb:389:in `block in ': + # recursive once + def once n + return %r/#{ + if n == 0 + true + else + once(n-1) # here + end + }/ox + end + x = once(128); x = once(7); x = once(16); + x =~ "true" && $~ + #=> "" (expected "true") once + Stderr output is not empty + bootstraptest.tmp.rb:3:in `once': stack level too deep (SystemStackError) + from bootstraptest.tmp.rb:7:in `block in once' + from bootstraptest.tmp.rb:3:in `once' + from bootstraptest.tmp.rb:7:in `block in once' + from bootstraptest.tmp.rb:3:in `once' + from bootstraptest.tmp.rb:7:in `block in once' + from bootstraptest.tmp.rb:3:in `once' + from bootstraptest.tmp.rb:7:in `block in once' + from bootstraptest.tmp.rb:3:in `once' + ... 125 levels... + from bootstraptest.tmp.rb:3:in `once' + from bootstraptest.tmp.rb:7:in `block in once' + from bootstraptest.tmp.rb:3:in `once' + from bootstraptest.tmp.rb:11:in `
' + Test_insns.rb FAIL 1/187 + FAIL 1/1197 tests failed + Make: *** [uncommon.mk:666: yes-btest-ruby] Error 1 + +--- bootstraptest/test_insns.rb ++++ bootstraptest/test_insns.rb +@@ -248,7 +248,7 @@ + end + }/ox + end +- x = once(128); x = once(7); x = once(16); ++ x = once(32); x = once(7); x = once(16); + x =~ "true" && $~ + }, + [ 'once', <<~'},', ], # { diff --git a/srcpkgs/ruby/template b/srcpkgs/ruby/template index d5db49edef4..588a1d89bcf 100644 --- a/srcpkgs/ruby/template +++ b/srcpkgs/ruby/template @@ -3,7 +3,7 @@ _ruby_abiver=2.6.0 pkgname=ruby version=2.6.5 -revision=1 +revision=2 build_style=gnu-configure configure_args="--enable-shared --disable-rpath DOXYGEN=/usr/bin/doxygen DOT=/usr/bin/dot PKG_CONFIG=/usr/bin/pkg-config" @@ -35,6 +35,13 @@ if [ "$CROSS_BUILD" ]; then hostmakedepends+=" ruby" fi +post_patch() { + [ "$XBPS_TARGET_LIBC" = "glibc" ] && return 0 + + echo "Patching out using binary gems for non-glibc..." + patch -sNp1 -i ${FILESDIR}/rubygems-avoid-platform-specific-gems.patch +} + pre_build() { # Force getaddrinfo detection. sed -e 's,\(checking_for("wide getaddrinfo") {try_\)run,\1link,' -i ext/socket/extconf.rb