summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2024-04-23 14:30:31 -0400
committerPeter Zhu <[email protected]>2024-04-23 15:29:42 -0400
commitb9109b270d129561f06bc2dcd6feaf5c43e82360 (patch)
treefbdae06fd3fcbadf2f15e7294b41069dc407251e
parent81433fd0f52b4214c0e788b6cd9f534b79ec03ba (diff)
Get error from dln_open when USE_SHARED_GC
Before, if dln_open failed to open RUBY_GC_LIBRARY_PATH, it would segfault because it would try to raise an error, which cannot happen because the GC has not been initialized yet. This commit changes dln_open to return the error that occurred so the caller can handle the error.
-rw-r--r--dln.c29
-rw-r--r--dln.h2
-rw-r--r--dmydln.c4
-rw-r--r--gc.c13
4 files changed, 22 insertions, 26 deletions
diff --git a/dln.c b/dln.c
index 3e08728a6b..ca520acd06 100644
--- a/dln.c
+++ b/dln.c
@@ -340,10 +340,9 @@ dln_disable_dlclose(void)
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
void *
-dln_open(const char *file)
+dln_open(const char *file, const char **error)
{
static const char incompatible[] = "incompatible library version";
- const char *error = NULL;
void *handle;
#if defined(_WIN32)
@@ -360,15 +359,15 @@ dln_open(const char *file)
free(winfile);
if (!handle) {
- error = dln_strerror();
- goto failed;
+ *error = dln_strerror();
+ return NULL;
}
# if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
FreeLibrary(handle);
- error = incompatible;
- goto failed;
+ *error = incompatible;
+ return NULL;
}
# endif
@@ -387,8 +386,8 @@ dln_open(const char *file)
/* Load file */
handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
if (handle == NULL) {
- error = dln_strerror();
- goto failed;
+ *error = dln_strerror();
+ return NULL;
}
# if defined(RUBY_EXPORT)
@@ -413,8 +412,8 @@ dln_open(const char *file)
if (libruby_name) {
dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
}
- error = incompatible;
- goto failed;
+ *error = incompatible;
+ return NULL;
}
}
}
@@ -422,9 +421,6 @@ dln_open(const char *file)
#endif
return handle;
-
- failed:
- dln_loaderror("%s - %s", error, file);
}
void *
@@ -501,7 +497,12 @@ void *
dln_load(const char *file)
{
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
- void *handle = dln_open(file);
+ const char *error = NULL;
+ void *handle = dln_open(file, &error);
+
+ if (handle == NULL) {
+ dln_loaderror("%s - %s", error, file);
+ }
#ifdef RUBY_DLN_CHECK_ABI
typedef unsigned long long abi_version_number;
diff --git a/dln.h b/dln.h
index 13eef58d9f..0bbbc73378 100644
--- a/dln.h
+++ b/dln.h
@@ -25,7 +25,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
char *dln_find_exe_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
char *dln_find_file_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
void *dln_load(const char*);
-void *dln_open(const char *file);
+void *dln_open(const char *file, const char **error);
void *dln_symbol(void*,const char*);
RUBY_SYMBOL_EXPORT_END
diff --git a/dmydln.c b/dmydln.c
index 22f40e82eb..70fd2c1d6c 100644
--- a/dmydln.c
+++ b/dmydln.c
@@ -21,9 +21,9 @@ dln_symbol(void *handle, const char *symbol)
UNREACHABLE_RETURN(NULL);
}
-NORETURN(void *dln_open(const char*));
+NORETURN(void *dln_open(const char *library, const char **error));
void*
-dln_open(const char *library)
+dln_open(const char *library, const char **error)
{
rb_loaderror("this executable file can't load extension libraries");
diff --git a/gc.c b/gc.c
index ef3e1538a0..d8898b2cf1 100644
--- a/gc.c
+++ b/gc.c
@@ -1900,20 +1900,15 @@ ruby_external_gc_init()
return;
}
- void *h = dln_open(gc_so_path);
+ const char *error = NULL;
+ void *h = dln_open(gc_so_path, &error);
if (!h) {
- rb_bug(
- "ruby_external_gc_init: Shared library %s cannot be opened.",
- gc_so_path
- );
+ rb_bug("ruby_external_gc_init: Shared library %s cannot be opened (%s)", gc_so_path, error);
}
void *gc_init_func = dln_symbol(h, "Init_GC");
if (!gc_init_func) {
- rb_bug(
- "ruby_external_gc_init: Init_GC func not exported by library %s",
- gc_so_path
- );
+ rb_bug("ruby_external_gc_init: Init_GC func not exported by library %s", gc_so_path);
}
map->init = gc_init_func;