mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
[Feature #18249] Implement ABI checking
Header file include/ruby/internal/abi.h contains RUBY_ABI_VERSION which is the ABI version. This value should be bumped whenever an ABI incompatible change is introduced. When loading dynamic libraries, Ruby will compare its own `ruby_abi_version` and the `ruby_abi_version` of the loaded library. If these two values don't match it will raise a `LoadError`. This feature can also be turned off by setting the environment variable `RUBY_RUBY_ABI_CHECK=0`. This feature will prevent cases where previously installed native gems fail in unexpected ways due to incompatibility of changes in header files. This will force the developer to recompile their gems to use the same header files as the built Ruby. In Ruby, the ABI version is exposed through `RbConfig::CONFIG["ruby_abi_version"]`.
This commit is contained in:
parent
37d5890e49
commit
3df16924b4
Notes:
git
2022-02-22 23:55:57 +09:00
8 changed files with 130 additions and 0 deletions
17
dln.c
17
dln.c
|
@ -426,12 +426,29 @@ dln_sym(void *handle, const char *symbol)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if RUBY_DLN_CHECK_ABI
|
||||
static bool
|
||||
abi_check_enabled_p(void)
|
||||
{
|
||||
const char *val = getenv("RUBY_ABI_CHECK");
|
||||
return val == NULL || !(val[0] == '0' && val[1] == '\0');
|
||||
}
|
||||
#endif
|
||||
|
||||
void *
|
||||
dln_load(const char *file)
|
||||
{
|
||||
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
|
||||
void *handle = dln_open(file);
|
||||
|
||||
#if RUBY_DLN_CHECK_ABI
|
||||
unsigned long long (*abi_version_fct)(void) = (unsigned long long(*)(void))dln_sym(handle, "ruby_abi_version");
|
||||
unsigned long long binary_abi_version = (*abi_version_fct)();
|
||||
if (binary_abi_version != ruby_abi_version() && abi_check_enabled_p()) {
|
||||
dln_loaderror("ABI version of binary is incompatible with this Ruby. Try rebuilding this binary.");
|
||||
}
|
||||
#endif
|
||||
|
||||
char *init_fct_name;
|
||||
init_funcname(&init_fct_name, file);
|
||||
void (*init_fct)(void) = (void(*)(void))dln_sym(handle, init_fct_name);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue