summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--variable.c52
2 files changed, 51 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 7b28323c99..bb4e65ac1f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Wed May 25 18:40:47 2011 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * variable.c (rb_const_get_0): Fix previous change. There were
+ possibilities when an autoload-specified library lacks
+ definition of the constant it was bound to. Once after such
+ library had already beed loaded, the autoload engine shall not
+ reload it. Instead the interpreter have to consider such
+ constant nonexistent. It results in a const_missing situation.
+
+ * variable.c (rb_autoload_load): ditto.
+
+ * variable.c (autoload_node): ditto.
+
Wed May 25 14:35:02 2011 URABE Shyouhei <shyouhei@ruby-lang.org>
* variable.c (rb_autoload_load): There is a race condition while
diff --git a/variable.c b/variable.c
index 7f5064521f..54bb153e2b 100644
--- a/variable.c
+++ b/variable.c
@@ -1352,16 +1352,29 @@ autoload_node(mod, id)
ID id;
{
st_data_t val, load, n = id;
- struct st_table *p = RCLASS(mod)->iv_tbl;
+ struct st_table *p, *q;
- if (p && st_lookup(p, autoload, &val)) {
- st_table *q = check_autoload_table((VALUE)val);
-
- if (q && st_lookup(q, n, &load)) {
- return (NODE *)load;
- }
+ if ((p = RCLASS(mod)->iv_tbl) == 0) {
+ return 0;
+ }
+ else if (!st_lookup(p, n, &val)) {
+ return 0;
+ }
+ else if (val != Qundef) {
+ return 0;
+ }
+ else if (!st_lookup(p, autoload, &val)) {
+ return 0;
+ }
+ else if ((q = check_autoload_table((VALUE)val)) == 0) {
+ return 0;
+ }
+ else if (!st_lookup(q, n, &load)) {
+ return 0;
+ }
+ else {
+ return (NODE *)load;
}
- return 0;
}
VALUE
@@ -1372,12 +1385,16 @@ rb_autoload_load(klass, id)
NODE *load = 0;
VALUE ret = 0;
- if ((load = autoload_node(klass, id)) != 0) {
- if ((ret = rb_require_safe(load->nd_lit, load->nd_nth)) != Qfalse) {
- (void) autoload_delete(klass, id);
- }
+ if ((load = autoload_node(klass, id)) == 0) {
+ return 0;
+ }
+ else if ((ret = rb_require_safe(load->nd_lit, load->nd_nth)) == Qfalse) {
+ return 0;
+ }
+ else {
+ (void) autoload_delete(klass, id);
+ return ret;
}
- return ret;
}
static VALUE
@@ -1440,7 +1457,14 @@ rb_const_get_0(klass, id, exclude, recurse)
while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
if (value == Qundef) {
rb_autoload_load(tmp, id);
- continue;
+ st_lookup(RCLASS(tmp)->iv_tbl, id, &value);
+ if (value == Qundef) {
+ /* the autoload above did not assign a constant */
+ break;
+ }
+ else {
+ continue;
+ }
}
if (exclude && tmp == rb_cObject && klass != rb_cObject) {
rb_warn("toplevel constant %s referenced by %s::%s",