diff options
author | Peter Zhu <[email protected]> | 2024-04-23 14:30:31 -0400 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2024-04-23 15:29:42 -0400 |
commit | b9109b270d129561f06bc2dcd6feaf5c43e82360 (patch) | |
tree | fbdae06fd3fcbadf2f15e7294b41069dc407251e | |
parent | 81433fd0f52b4214c0e788b6cd9f534b79ec03ba (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.c | 29 | ||||
-rw-r--r-- | dln.h | 2 | ||||
-rw-r--r-- | dmydln.c | 4 | ||||
-rw-r--r-- | gc.c | 13 |
4 files changed, 22 insertions, 26 deletions
@@ -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; @@ -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 @@ -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"); @@ -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; |