From: Nobuyoshi Nakada Date: 2006-12-18T23:46:23+09:00 Subject: [ruby-dev:30023] autoloading static linked extension なかだです。 http://moonrock.jp/~don/d/200612.html#d08_t2 の件ですが、 Init_ext()ではloading_tblに入らないのが原因です。 とりあえず[ruby-dev:29523]の際に作ったパッチです。ext/extmk.rb は1.8も共通。 Index: eval.c =================================================================== RCS file: /pub/cvs/ruby/eval.c,v retrieving revision 1.616.2.194 diff -U 2 -p -r1.616.2.194 eval.c --- eval.c 10 Sep 2006 00:18:39 -0000 1.616.2.194 +++ eval.c 13 Sep 2006 02:05:31 -0000 @@ -6927,5 +6927,14 @@ static st_table *loading_tbl; #endif -static char * + +static const char *const loadable_ext[] = { + ".rb", DLEXT, +#ifdef DLEXT2 + DLEXT2, +#endif + 0 +}; + +static int rb_feature_p(feature, ext, rb) const char *feature, *ext; @@ -6933,5 +6942,5 @@ rb_feature_p(feature, ext, rb) { VALUE v; - char *f, *e; + const char *f, *e; long i, len, elen; @@ -6947,5 +6956,6 @@ rb_feature_p(feature, ext, rb) v = RARRAY(rb_features)->ptr[i]; f = StringValuePtr(v); - if (strncmp(f, feature, len) != 0) continue; + if (RSTRING_LEN(v) < len || strncmp(f, feature, len) != 0) + continue; if (!*(e = f + len)) { if (ext) continue; @@ -6960,32 +6970,32 @@ rb_feature_p(feature, ext, rb) } } + if (loading_tbl) { + e = ext; + if (!st_lookup(loading_tbl, (st_data_t)feature, 0)) { + char *buf; + + if (ext) return 0; + buf = ALLOCA_N(char, len+8); + strcpy(buf, feature); + for (i = 0; (e = loadable_ext[i]) != 0; i++) { + strcpy(buf + len, loadable_ext[i]); + if (st_lookup(loading_tbl, (st_data_t)buf, 0)) { + break; + } + } + } + return !e ? 'u' : strcmp(e, ".rb") ? 's' : 'r'; + } return 0; } -static const char *const loadable_ext[] = { - ".rb", DLEXT, -#ifdef DLEXT2 - DLEXT2, -#endif - 0 -}; - int rb_provided(feature) const char *feature; { - int i; - char *buf; + int c; if (rb_feature_p(feature, 0, Qfalse)) return Qtrue; - if (!loading_tbl) return Qfalse; - if (st_lookup(loading_tbl, (st_data_t)feature, 0)) return Qtrue; - buf = ALLOCA_N(char, strlen(feature)+8); - strcpy(buf, feature); - for (i=0; ; i++) { - if (!loadable_ext[i]) break; - strcpy(buf+strlen(feature), loadable_ext[i]); - if (st_lookup(loading_tbl, (st_data_t)buf, 0)) return Qtrue; } return Qfalse; @@ -7006,17 +7016,39 @@ rb_provide(feature) } -static int -load_wait(ftptr) - char *ftptr; +static char * +load_lock(ftptr) + const char *ftptr; { st_data_t th; - if (!loading_tbl) return Qfalse; - if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return Qfalse; + if (!loading_tbl || + !st_lookup(loading_tbl, (st_data_t)ftptr, &th)) + { + /* loading ruby library should be serialized. */ + if (!loading_tbl) { + loading_tbl = st_init_strtable(); + } + /* partial state */ + ftptr = ruby_strdup(ftptr); + st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); + return (char *)ftptr; + } do { - if ((rb_thread_t)th == curr_thread) return Qtrue; + if ((rb_thread_t)th == curr_thread) return 0; CHECK_INTS; } while (st_lookup(loading_tbl, (st_data_t)ftptr, &th)); - return Qtrue; + return 0; +} + +static void +load_unlock(const char *ftptr) +{ + if (ftptr) { + st_data_t key = (st_data_t)ftptr; + + if (st_delete(loading_tbl, &key, 0)) { + free((char *)key); + } + } } @@ -7149,16 +7181,9 @@ rb_require_safe(fname, safe) found = search_required(fname, &feature, &path); if (found) { - if (!path || load_wait(RSTRING(feature)->ptr)) { + if (!path || !(ftptr = load_lock(RSTRING_PTR(feature)))) { result = Qfalse; } else { ruby_safe_level = 0; - /* loading ruby library should be serialized. */ - if (!loading_tbl) { - loading_tbl = st_init_strtable(); - } - /* partial state */ - ftptr = ruby_strdup(RSTRING_PTR(feature)); - st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); switch (found) { case 'r': @@ -7187,9 +7212,5 @@ rb_require_safe(fname, safe) SCOPE_SET(saved.vmode); ruby_safe_level = saved.safe; - if (ftptr) { - if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */ - free(ftptr); - } - } + load_unlock(ftptr); if (state) JUMP_TAG(state); if (NIL_P(result)) { @@ -7210,4 +7231,22 @@ rb_require(fname) } +void +ruby_init_ext(name, init) + const char *name; + void (*init) _((void)); +{ + ruby_current_node = 0; + ruby_sourcefile = rb_source_filename(name); + ruby_sourceline = 0; + ruby_frame->callee = 0; + ruby_frame->this_func = 0; + VIS_SET(VIS_PUBLIC); + if (load_lock(name)) { + (*init)(); + rb_provide(name); + load_unlock(name); + } +} + static void secure_visibility(self) Index: eval.c =================================================================== RCS file: /pub/cvs/ruby/eval.c,v retrieving revision 1.946 diff -U 2 -p -r1.946 eval.c --- eval.c 18 Sep 2006 01:58:59 -0000 1.946 +++ eval.c 19 Sep 2006 04:55:21 -0000 @@ -6821,9 +6821,18 @@ static st_table *loading_tbl; #endif + +static const char *const loadable_ext[] = { + ".rb", DLEXT, +#ifdef DLEXT2 + DLEXT2, +#endif + 0 +}; + static int rb_feature_p(const char *feature, const char *ext, int rb) { VALUE v; - char *f, *e; + const char *f, *e; long i, len, elen; @@ -6839,5 +6848,6 @@ rb_feature_p(const char *feature, const v = RARRAY_PTR(rb_features)[i]; f = StringValuePtr(v); - if (strncmp(f, feature, len) != 0) continue; + if (RSTRING_LEN(v) < len || strncmp(f, feature, len) != 0) + continue; if (!*(e = f + len)) { if (ext) continue; @@ -6852,15 +6862,24 @@ rb_feature_p(const char *feature, const } } + if (loading_tbl) { + e = ext; + if (!st_lookup(loading_tbl, (st_data_t)feature, 0)) { + char *buf; + + if (ext) return 0; + buf = ALLOCA_N(char, len+8); + strcpy(buf, feature); + for (i = 0; (e = loadable_ext[i]) != 0; i++) { + strcpy(buf + len, loadable_ext[i]); + if (st_lookup(loading_tbl, (st_data_t)buf, 0)) { + break; + } + } + } + return !e ? 'u' : strcmp(e, ".rb") ? 's' : 'r'; + } return 0; } -static const char *const loadable_ext[] = { - ".rb", DLEXT, -#ifdef DLEXT2 - DLEXT2, -#endif - 0 -}; - static int search_required(VALUE, VALUE *); @@ -6868,24 +6887,12 @@ int rb_provided(const char *feature) { - int i; - char *buf; + int c; VALUE fname; if (rb_feature_p(feature, 0, Qfalse)) return Qtrue; - if (loading_tbl) { - if (st_lookup(loading_tbl, (st_data_t)feature, 0)) return Qtrue; - buf = ALLOCA_N(char, strlen(feature)+8); - strcpy(buf, feature); - for (i=0; loadable_ext[i]; i++) { - strcpy(buf+strlen(feature), loadable_ext[i]); - if (st_lookup(loading_tbl, (st_data_t)buf, 0)) return Qtrue; - } - } - if (search_required(rb_str_new2(feature), &fname)) { + if ((c = search_required(rb_str_new2(feature), &fname)) != 0) { feature = RSTRING_PTR(fname); - if (rb_feature_p(feature, 0, Qfalse)) - return Qtrue; - if (loading_tbl && st_lookup(loading_tbl, (st_data_t)feature, 0)) + if (rb_feature_p(feature, c ? strrchr(feature, '.') : 0, Qfalse)) return Qtrue; } @@ -6905,16 +6912,38 @@ rb_provide(const char *feature) } -static int -load_wait(char *ftptr) +static char * +load_lock(const char *ftptr) { st_data_t th; - if (!loading_tbl) return Qfalse; - if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return Qfalse; + if (!loading_tbl || + !st_lookup(loading_tbl, (st_data_t)ftptr, &th)) + { + /* loading ruby library should be serialized. */ + if (!loading_tbl) { + loading_tbl = st_init_strtable(); + } + /* partial state */ + ftptr = ruby_strdup(ftptr); + st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); + return (char *)ftptr; + } do { - if ((rb_thread_t)th == curr_thread) return Qtrue; + if ((rb_thread_t)th == curr_thread) return 0; CHECK_INTS; } while (st_lookup(loading_tbl, (st_data_t)ftptr, &th)); - return Qtrue; + return 0; +} + +static void +load_unlock(const char *ftptr) +{ + if (ftptr) { + st_data_t key = (st_data_t)ftptr; + + if (st_delete(loading_tbl, &key, 0)) { + free((char *)key); + } + } } @@ -7063,5 +7092,5 @@ rb_require_safe(VALUE fname, int safe) found = search_required(fname, &path); if (found) { - if (!path || load_wait(RSTRING_PTR(path))) { + if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { result = Qfalse; } @@ -7105,9 +7134,5 @@ rb_require_safe(VALUE fname, int safe) POP_CREF(); POP_SCOPE(); - if (ftptr) { - if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */ - free(ftptr); - } - } + load_unlock(ftptr); if (state) JUMP_TAG(state); if (NIL_P(result)) { @@ -7127,4 +7152,20 @@ rb_require(const char *fname) } +void +ruby_init_ext(const char *name, void (*init)(void)) +{ + ruby_current_node = 0; + ruby_sourcefile = rb_source_filename(name); + ruby_sourceline = 0; + ruby_frame->callee = 0; + ruby_frame->this_func = 0; + VIS_SET(VIS_PUBLIC); + if (load_lock(name)) { + (*init)(); + rb_provide(name); + load_unlock(name); + } +} + static void secure_visibility(VALUE self) Index: ext/extmk.rb =================================================================== RCS file: /pub/cvs/ruby/ext/extmk.rb,v retrieving revision 1.101 diff -U 2 -p -r1.101 extmk.rb --- ext/extmk.rb 16 Sep 2006 07:06:36 -0000 1.101 +++ ext/extmk.rb 19 Sep 2006 04:55:28 -0000 @@ -452,12 +452,9 @@ unless $extlist.empty? #include "ruby.h" -#define init(func, name) { \ - void func _((void)); \ - ruby_sourcefile = src = rb_source_filename(name); \ - func(); \ - rb_provide(src); \ -} +#define init(func, name) {void func _((void)); ruby_init_ext(name, func);} + +void ruby_init_ext _((const char *name, void (*init)(void))); -void Init_ext _((void))\n{\n char *src;#$extinit} +void Init_ext _((void))\n{\n#$extinit} } if !modified?(extinit.c, MTIMES) || IO.read(extinit.c) != src -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦