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.
This commit is contained in:
Peter Zhu 2024-07-04 16:15:00 -04:00
Родитель 8fd2df529b
Коммит e2ceded2c6
3 изменённых файлов: 54 добавлений и 12 удалений

Просмотреть файл

@ -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"

35
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

Просмотреть файл

@ -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