2020#include "ccan/list/list.h"
2121#include "id_table.h"
2222#include "debug_counter.h"
23+ #include "vm_core.h"
2324
2425struct rb_id_table * rb_global_tbl ;
2526static ID autoload , classpath , tmp_classpath , classid ;
@@ -1859,6 +1860,7 @@ struct autoload_data_i {
18591860 rb_const_flag_t flag ;
18601861 VALUE value ;
18611862 struct autoload_state * state ; /* points to on-stack struct */
1863+ rb_serial_t fork_gen ;
18621864};
18631865
18641866static void
@@ -1881,8 +1883,18 @@ static const rb_data_type_t autoload_data_i_type = {
18811883 0 , 0 , RUBY_TYPED_FREE_IMMEDIATELY
18821884};
18831885
1884- #define check_autoload_data (av ) \
1885- (struct autoload_data_i *)rb_check_typeddata((av), &autoload_data_i_type)
1886+ static struct autoload_data_i *
1887+ get_autoload_data (VALUE av )
1888+ {
1889+ struct autoload_data_i * ele = rb_check_typeddata (av , & autoload_data_i_type );
1890+
1891+ /* do not reach across stack for ->state after forking: */
1892+ if (ele && ele -> state && ele -> fork_gen != GET_VM ()-> fork_gen ) {
1893+ ele -> state = 0 ;
1894+ ele -> fork_gen = 0 ;
1895+ }
1896+ return ele ;
1897+ }
18861898
18871899RUBY_FUNC_EXPORTED void
18881900rb_autoload (VALUE mod , ID id , const char * file )
@@ -1982,7 +1994,7 @@ check_autoload_required(VALUE mod, ID id, const char **loadingpath)
19821994 const char * loading ;
19831995 int safe ;
19841996
1985- if (!(load = autoload_data (mod , id )) || !(ele = check_autoload_data (load ))) {
1997+ if (!(load = autoload_data (mod , id )) || !(ele = get_autoload_data (load ))) {
19861998 return 0 ;
19871999 }
19882000 file = ele -> feature ;
@@ -2020,7 +2032,7 @@ rb_autoloading_value(VALUE mod, ID id, VALUE* value, rb_const_flag_t *flag)
20202032 VALUE load ;
20212033 struct autoload_data_i * ele ;
20222034
2023- if (!(load = autoload_data (mod , id )) || !(ele = check_autoload_data (load ))) {
2035+ if (!(load = autoload_data (mod , id )) || !(ele = get_autoload_data (load ))) {
20242036 return 0 ;
20252037 }
20262038 if (ele -> state && ele -> state -> thread == rb_thread_current ()) {
@@ -2087,8 +2099,9 @@ autoload_reset(VALUE arg)
20872099 int need_wakeups = 0 ;
20882100
20892101 if (state -> ele -> state == state ) {
2090- need_wakeups = 1 ;
2091- state -> ele -> state = 0 ;
2102+ need_wakeups = 1 ;
2103+ state -> ele -> state = 0 ;
2104+ state -> ele -> fork_gen = 0 ;
20922105 }
20932106
20942107 /* At the last, move a value defined in autoload to constant table */
@@ -2170,7 +2183,7 @@ rb_autoload_load(VALUE mod, ID id)
21702183 if (src && loading && strcmp (src , loading ) == 0 ) return Qfalse ;
21712184
21722185 /* set ele->state for a marker of autoloading thread */
2173- if (!(ele = check_autoload_data (load ))) {
2186+ if (!(ele = get_autoload_data (load ))) {
21742187 return Qfalse ;
21752188 }
21762189
@@ -2180,6 +2193,7 @@ rb_autoload_load(VALUE mod, ID id)
21802193 state .thread = rb_thread_current ();
21812194 if (!ele -> state ) {
21822195 ele -> state = & state ;
2196+ ele -> fork_gen = GET_VM ()-> fork_gen ;
21832197
21842198 /*
21852199 * autoload_reset will wake up any threads added to this
@@ -2217,7 +2231,7 @@ rb_autoload_p(VALUE mod, ID id)
22172231 }
22182232 load = check_autoload_required (mod , id , 0 );
22192233 if (!load ) return Qnil ;
2220- return (ele = check_autoload_data (load )) ? ele -> feature : Qnil ;
2234+ return (ele = get_autoload_data (load )) ? ele -> feature : Qnil ;
22212235}
22222236
22232237void
@@ -2646,7 +2660,7 @@ current_autoload_data(VALUE mod, ID id)
26462660 struct autoload_data_i * ele ;
26472661 VALUE load = autoload_data (mod , id );
26482662 if (!load ) return 0 ;
2649- ele = check_autoload_data (load );
2663+ ele = get_autoload_data (load );
26502664 if (!ele ) return 0 ;
26512665 /* for autoloading thread, keep the defined value to autoloading storage */
26522666 if (ele -> state && (ele -> state -> thread == rb_thread_current ())) {
0 commit comments