aboutsummaryrefslogtreecommitdiffstats
path: root/dln.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2022-02-17 17:49:16 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2022-02-17 20:29:50 +0900
commit992bdfea2d3030c041a33d58221ffdcd91f1a999 (patch)
tree5c710945a25e5af674bd7b7d4557cd14bcbf29da /dln.c
parent5952a1f201cfed38277b4fafa0624c1a048edb6d (diff)
downloadruby-992bdfea2d3030c041a33d58221ffdcd91f1a999.tar.gz
Refine the load error message
Show the linked ruby library name when failed to load extension built against different ruby library.
Diffstat (limited to 'dln.c')
-rw-r--r--dln.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/dln.c b/dln.c
index 5c1e6f8c02..902f187283 100644
--- a/dln.c
+++ b/dln.c
@@ -269,16 +269,31 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine)
#ifdef USE_DLN_DLOPEN
# include "ruby/internal/stdbool.h"
# include "internal/warnings.h"
+static bool
+dln_incompatible_func(void *handle, const char *funcname, void *const fp, const char **libname)
+{
+ Dl_info dli;
+ void *ex = dlsym(handle, funcname);
+ if (!ex) return false;
+ if (ex == fp) return false;
+ if (dladdr(ex, &dli)) {
+ *libname = dli.dli_fname;
+ }
+ return true;
+}
+
COMPILER_WARNING_PUSH
#if defined(__clang__) || GCC_VERSION_SINCE(4, 2, 0)
COMPILER_WARNING_IGNORED(-Wpedantic)
#endif
static bool
-dln_incompatible_library_p(void *handle)
+dln_incompatible_library_p(void *handle, const char **libname)
{
- void *ex = dlsym(handle, EXTERNAL_PREFIX"ruby_xmalloc");
- void *const fp = (void *)ruby_xmalloc;
- return ex && ex != fp;
+#define check_func(func) \
+ if (dln_incompatible_func(handle, EXTERNAL_PREFIX #func, (void *)&func, libname)) \
+ return true
+ check_func(ruby_xmalloc);
+ return false;
}
COMPILER_WARNING_POP
#endif
@@ -356,13 +371,20 @@ dln_open(const char *file)
# if defined(RUBY_EXPORT)
{
- if (dln_incompatible_library_p(handle)) {
+ const char *libruby_name = NULL;
+ if (dln_incompatible_library_p(handle, &libruby_name)) {
if (dln_disable_dlclose()) {
/* dlclose() segfaults */
+ if (libruby_name) {
+ dln_fatalerror("linked to incompatible %s - %s", libruby_name, file);
+ }
dln_fatalerror("%s - %s", incompatible, file);
}
else {
dlclose(handle);
+ if (libruby_name) {
+ dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
+ }
error = incompatible;
goto failed;
}