summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-10-08 12:54:26 -0900
committerGitHub <noreply@github.com>2021-10-08 14:54:26 -0700
commit08759edea8fb75d46c3e75217e6613465426a0d2 (patch)
tree7fb4c92e54b0e5fc3767ceeb6c0db645374ae54f /variable.c
parentded5a66cb994c5731a17bc9a2420042248a2f1fe (diff)
Remove autoload for constant if the autoload fails
Previously, if an autoload failed (the file was loaded, but the constant was not defined by the autoloaded file). Ruby will try to autoload again if you delete the autoloaded file from $LOADED_FEATURES. With this change, the autoload and the constant itself are removed as soon as it fails. To handle cases where multiple threads are autoloading, when deleting an autoload, handle the case where another thread already deleted it. Fixes [Bug #15790]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4715 Merged-By: jeremyevans <code@jeremyevans.net>
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/variable.c b/variable.c
index 8bdc733a4c..5712ccf0ba 100644
--- a/variable.c
+++ b/variable.c
@@ -2237,23 +2237,26 @@ autoload_delete(VALUE mod, ID id)
struct autoload_const *ac;
st_delete(tbl, &n, &load);
- ele = get_autoload_data((VALUE)load, &ac);
- VM_ASSERT(ele);
- if (ele) {
- VM_ASSERT(!list_empty(&ele->constants));
- }
+ /* Qfalse can indicate already deleted */
+ if (load != Qfalse) {
+ ele = get_autoload_data((VALUE)load, &ac);
+ VM_ASSERT(ele);
+ if (ele) {
+ VM_ASSERT(!list_empty(&ele->constants));
+ }
- /*
- * we must delete here to avoid "already initialized" warnings
- * with parallel autoload. Using list_del_init here so list_del
- * works in autoload_c_free
- */
- list_del_init(&ac->cnode);
+ /*
+ * we must delete here to avoid "already initialized" warnings
+ * with parallel autoload. Using list_del_init here so list_del
+ * works in autoload_c_free
+ */
+ list_del_init(&ac->cnode);
- if (tbl->num_entries == 0) {
- n = autoload;
- st_delete(RCLASS_IV_TBL(mod), &n, &val);
- }
+ if (tbl->num_entries == 0) {
+ n = autoload;
+ st_delete(RCLASS_IV_TBL(mod), &n, &val);
+ }
+ }
}
}
@@ -2502,7 +2505,10 @@ rb_autoload_load(VALUE mod, ID id)
result = rb_ensure(autoload_require, (VALUE)&state,
autoload_reset, (VALUE)&state);
- if (flag > 0 && (ce = rb_const_lookup(mod, id))) {
+ if (!(ce = rb_const_lookup(mod, id)) || ce->value == Qundef) {
+ rb_const_remove(mod, id);
+ }
+ else if (flag > 0) {
ce->flag |= flag;
}
RB_GC_GUARD(load);