summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2024-07-04 16:15:00 -0400
committerPeter Zhu <peter@peterzhu.ca>2024-07-05 14:05:58 -0400
commite2ceded2c603f5f35df5c0d8757a48a1fa1f0f8f (patch)
tree9df2ffda20649762720b7ac67edb4ae7fd299592
parent8fd2df529b8c9a172604c5cde478abe54c30b47d (diff)
Change external GC to use directory at configure
This commit changes the external GC API to use `--with-shared-gc=DIR` at configure time with a directory of the external GC and uses `RUBY_GC_LIBRARY` environment variable to load the external GC at runtime.
-rw-r--r--configure.ac2
-rw-r--r--gc.c35
-rw-r--r--tool/m4/ruby_shared_gc.m429
3 files changed, 54 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac
index f8c814c22c..014ca40f4c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4751,7 +4751,7 @@ config_summary "target OS" "$target_os"
config_summary "compiler" "$CC"
config_summary "with thread" "$THREAD_MODEL"
config_summary "with coroutine" "$coroutine_type"
-config_summary "with shared GC" "$with_shared_gc"
+config_summary "with shared GC" "$shared_gc_summary"
config_summary "enable shared libs" "$ENABLE_SHARED"
config_summary "dynamic library ext" "$DLEXT"
config_summary "CFLAGS" "$cflags"
diff --git a/gc.c b/gc.c
index 8a7ce3f949..fc83ace418 100644
--- a/gc.c
+++ b/gc.c
@@ -748,14 +748,39 @@ typedef struct gc_function_map {
static rb_gc_function_map_t rb_gc_functions;
-# define RUBY_GC_LIBRARY_PATH "RUBY_GC_LIBRARY_PATH"
+# define RUBY_GC_LIBRARY "RUBY_GC_LIBRARY"
static void
ruby_external_gc_init(void)
{
- char *gc_so_path = getenv(RUBY_GC_LIBRARY_PATH);
+ // Assert that the directory path ends with a /
+ GC_ASSERT(SHARED_GC_DIR[strlen(SHARED_GC_DIR) - 2] == '/');
+
+ char *gc_so_file = getenv(RUBY_GC_LIBRARY);
+
+ char *gc_so_path = NULL;
void *handle = NULL;
- if (gc_so_path && dln_supported_p()) {
+ if (gc_so_file && dln_supported_p()) {
+ /* Check to make sure that gc_so_file matches /[\w-_.]+/ so that it does
+ * not load a shared object outside of the directory. */
+ for (size_t i = 0; i < strlen(gc_so_file); i++) {
+ char c = gc_so_file[i];
+ if (isalnum(c)) continue;
+ switch (c) {
+ case '-':
+ case '_':
+ case '.':
+ break;
+ default:
+ rb_bug("Only alphanumeric, dash, underscore, and period is allowed in "RUBY_GC_LIBRARY"");
+ }
+ }
+
+ gc_so_path = alloca(strlen(SHARED_GC_DIR) + strlen(gc_so_file) + 1);
+ strcpy(gc_so_path, SHARED_GC_DIR);
+ strcpy(gc_so_path + strlen(SHARED_GC_DIR), gc_so_file);
+ gc_so_path[strlen(SHARED_GC_DIR) + strlen(gc_so_file)] = '\0';
+
char error[1024];
handle = dln_open(gc_so_path, error, sizeof(error));
if (!handle) {
@@ -4625,8 +4650,8 @@ void
Init_GC(void)
{
#if USE_SHARED_GC
- if (getenv(RUBY_GC_LIBRARY_PATH) != NULL && !dln_supported_p()) {
- rb_warn(RUBY_GC_LIBRARY_PATH " is ignored because this executable file can't load extension libraries");
+ if (getenv(RUBY_GC_LIBRARY) != NULL && !dln_supported_p()) {
+ rb_warn(RUBY_GC_LIBRARY " is ignored because this executable file can't load extension libraries");
}
#endif
diff --git a/tool/m4/ruby_shared_gc.m4 b/tool/m4/ruby_shared_gc.m4
index a27b9b8505..a65c26b876 100644
--- a/tool/m4/ruby_shared_gc.m4
+++ b/tool/m4/ruby_shared_gc.m4
@@ -1,19 +1,36 @@
dnl -*- Autoconf -*-
AC_DEFUN([RUBY_SHARED_GC],[
AC_ARG_WITH(shared-gc,
- AS_HELP_STRING([--with-shared-gc],
- [Enable replacement of Ruby's GC from a shared library.]),
- [with_shared_gc=$withval], [unset with_shared_gc]
+ AS_HELP_STRING([--with-shared-gc=DIR],
+ [Enable replacement of Ruby's GC from a shared library in the specified directory.]),
+ [shared_gc_dir=$withval], [unset shared_gc_dir]
)
-AC_SUBST([with_shared_gc])
AC_MSG_CHECKING([if Ruby is build with shared GC support])
-AS_IF([test "$with_shared_gc" = "yes"], [
+AS_IF([test x"$shared_gc_dir" != x], [
AC_MSG_RESULT([yes])
+
+ # Ensure that shared_gc_dir is always an absolute path so that Ruby
+ # never loads a shared GC from a relative path
+ AS_CASE(["$shared_gc_dir"],
+ [/*], [shared_gc_dir=$shared_gc_dir],
+ [shared_gc_dir=`pwd`/$shared_gc_dir]
+ )
+
+ # Ensure that shared_gc_dir always terminates with a /
+ AS_CASE(["$shared_gc_dir"],
+ [*/], [],
+ [shared_gc_dir="$shared_gc_dir/"]
+ )
+
AC_DEFINE([USE_SHARED_GC], [1])
+ AC_DEFINE_UNQUOTED([SHARED_GC_DIR], "$shared_gc_dir")
+
+ shared_gc_summary="yes (in $shared_gc_dir)"
], [
AC_MSG_RESULT([no])
- with_shared_gc="no"
AC_DEFINE([USE_SHARED_GC], [0])
+
+ shared_gc_summary="no"
])
])dnl