diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index eaa265fcfa..94570597ba 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -611,6 +611,65 @@ assert_equal 'ok', %q{ 'ok' } +# $DEBUG, $VERBOSE are Ractor local +assert_equal 'true', %q{ + $DEBUG = true + $VERBOSE = true + + def ractor_local_globals + /a(b)(c)d/ =~ 'abcd' # for $~ + `echo foo` + + { + # ractor-local (derived from created ractor): debug + '$DEBUG' => $DEBUG, + '$-d' => $-d, + + # ractor-local (derived from created ractor): verbose + '$VERBOSE' => $VERBOSE, + '$-w' => $-w, + '$-W' => $-W, + '$-v' => $-v, + + # process-local (readonly): other commandline parameters + '$-p' => $-p, + '$-l' => $-l, + '$-a' => $-a, + + # process-local (readonly): getpid + '$$' => $$, + + # thread local: process result + '$?' => $?, + + # scope local: match + '$~' => $~.inspect, + '$&' => $&, + '$`' => $`, + '$\'' => $', + '$+' => $+, + '$1' => $1, + + # scope local: last line + '$_' => $_, + + # scope local: last backtrace + '$@' => $@, + '$!' => $!, + + # ractor local: stdin, out, err + '$stdin' => $stdin.inspect, + '$stdout' => $stdout.inspect, + '$stderr' => $stderr.inspect, + } + end + + h = Ractor.new do + ractor_local_globals + end.take + ractor_local_globals == h #=> true +} + # selfs are different objects assert_equal 'false', %q{ r = Ractor.new do diff --git a/common.mk b/common.mk index 10910d1775..a8719ca4e6 100644 --- a/common.mk +++ b/common.mk @@ -10943,6 +10943,7 @@ re.$(OBJEXT): $(top_srcdir)/internal/imemo.h re.$(OBJEXT): $(top_srcdir)/internal/re.h re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h re.$(OBJEXT): $(top_srcdir)/internal/string.h +re.$(OBJEXT): $(top_srcdir)/internal/variable.h re.$(OBJEXT): $(top_srcdir)/internal/warnings.h re.$(OBJEXT): {$(VPATH)}assert.h re.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -10955,9 +10956,11 @@ re.$(OBJEXT): {$(VPATH)}backward/2/long_long.h re.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h re.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h re.$(OBJEXT): {$(VPATH)}config.h +re.$(OBJEXT): {$(VPATH)}constant.h re.$(OBJEXT): {$(VPATH)}defines.h re.$(OBJEXT): {$(VPATH)}encindex.h re.$(OBJEXT): {$(VPATH)}encoding.h +re.$(OBJEXT): {$(VPATH)}id_table.h re.$(OBJEXT): {$(VPATH)}intern.h re.$(OBJEXT): {$(VPATH)}internal.h re.$(OBJEXT): {$(VPATH)}internal/anyargs.h diff --git a/eval.c b/eval.c index 87c048be3f..9a10cb46b1 100644 --- a/eval.c +++ b/eval.c @@ -2084,6 +2084,9 @@ Init_eval(void) rb_define_virtual_variable("$@", errat_getter, errat_setter); rb_define_virtual_variable("$!", errinfo_getter, 0); + rb_gvar_ractor_local("$@"); + rb_gvar_ractor_local("$!"); + rb_define_global_function("raise", f_raise, -1); rb_define_global_function("fail", f_raise, -1); diff --git a/io.c b/io.c index c986ffbc47..3b4ae6d60b 100644 --- a/io.c +++ b/io.c @@ -13543,6 +13543,7 @@ Init_IO(void) rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter); rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE); + rb_gvar_ractor_local("$_"); rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1); rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1); @@ -13764,6 +13765,8 @@ Init_IO(void) ARGF.filename = rb_str_new2("-"); rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set); + rb_gvar_ractor_local("$-i"); + rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter); #if defined (_WIN32) || defined(__CYGWIN__) diff --git a/process.c b/process.c index 8abb3ea86f..90db3c5677 100644 --- a/process.c +++ b/process.c @@ -8445,6 +8445,10 @@ InitVM_process(void) #define rb_intern(str) rb_intern_const(str) rb_define_virtual_variable("$?", get_CHILD_STATUS, 0); rb_define_virtual_variable("$$", get_PROCESS_ID, 0); + + rb_gvar_ractor_local("$$"); + rb_gvar_ractor_local("$?"); + rb_define_global_function("exec", f_exec, -1); rb_define_global_function("fork", rb_f_fork, 0); rb_define_global_function("exit!", rb_f_exit_bang, -1); diff --git a/ractor.c b/ractor.c index 5bc65a0491..68ac5a25fe 100644 --- a/ractor.c +++ b/ractor.c @@ -1373,6 +1373,10 @@ ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VAL r->r_stdout = rb_io_prep_stdout(); r->r_stderr = rb_io_prep_stderr(); + rb_ractor_t *cr = rb_ec_ractor_ptr(ec); + r->verbose = cr->verbose; + r->debug = cr->debug; + rb_thread_create_ractor(r, args, block); RB_GC_GUARD(rv); diff --git a/ractor.h b/ractor.h index d3de06b559..1afd91b77c 100644 --- a/ractor.h +++ b/ractor.h @@ -125,6 +125,8 @@ struct rb_ractor_struct { VALUE r_stdin; VALUE r_stdout; VALUE r_stderr; + VALUE verbose; + VALUE debug; }; // rb_ractor_t is defined in vm_core.h rb_ractor_t *rb_ractor_main_alloc(void); diff --git a/re.c b/re.c index badd321782..020ba7b6d6 100644 --- a/re.c +++ b/re.c @@ -19,6 +19,7 @@ #include "internal/imemo.h" #include "internal/re.h" #include "internal/string.h" +#include "internal/variable.h" #include "regint.h" #include "ruby/encoding.h" #include "ruby/re.h" @@ -4052,6 +4053,12 @@ Init_Regexp(void) rb_define_virtual_variable("$'", postmatch_getter, 0); rb_define_virtual_variable("$+", last_paren_match_getter, 0); + rb_gvar_ractor_local("$~"); + rb_gvar_ractor_local("$&"); + rb_gvar_ractor_local("$`"); + rb_gvar_ractor_local("$'"); + rb_gvar_ractor_local("$+"); + rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter); rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter); rb_define_virtual_variable("$-K", kcode_getter, kcode_setter); diff --git a/ruby.c b/ruby.c index 9ca980dfbd..4feae7757a 100644 --- a/ruby.c +++ b/ruby.c @@ -63,6 +63,7 @@ #include "ruby/thread.h" #include "ruby/util.h" #include "ruby/version.h" +#include "ruby/internal/error.h" #ifndef MAXPATHLEN # define MAXPATHLEN 1024 @@ -2021,6 +2022,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) rb_define_readonly_boolean("$-l", opt->do_line); rb_define_readonly_boolean("$-a", opt->do_split); + rb_gvar_ractor_local("$-p"); + rb_gvar_ractor_local("$-l"); + rb_gvar_ractor_local("$-a"); + if ((rb_e_script = opt->e_script) != 0) { rb_gc_register_mark_object(opt->e_script); } @@ -2430,16 +2435,24 @@ forbid_setid(const char *s, const ruby_cmdline_options_t *opt) rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s); } +static VALUE +verbose_getter(ID id, VALUE *ptr) +{ + return *rb_ruby_verbose_ptr(); +} + static void verbose_setter(VALUE val, ID id, VALUE *variable) { - *variable = RTEST(val) ? Qtrue : val; + *rb_ruby_verbose_ptr() = RTEST(val) ? Qtrue : val; } static VALUE -opt_W_getter(ID id, VALUE *variable) +opt_W_getter(ID id, VALUE *dmy) { - switch (*variable) { + VALUE v = *rb_ruby_verbose_ptr(); + + switch (v) { case Qnil: return INT2FIX(0); case Qfalse: @@ -2451,16 +2464,35 @@ opt_W_getter(ID id, VALUE *variable) } } +static VALUE +debug_getter(ID id, VALUE *dmy) +{ + return *rb_ruby_debug_ptr(); +} + +static void +debug_setter(VALUE val, ID id, VALUE *dmy) +{ + *rb_ruby_debug_ptr() = val; +} + /*! Defines built-in variables */ void ruby_prog_init(void) { - rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter); - rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter); - rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter); - rb_define_hooked_variable("$-W", &ruby_verbose, opt_W_getter, rb_gvar_readonly_setter); - rb_define_variable("$DEBUG", &ruby_debug); - rb_define_variable("$-d", &ruby_debug); + rb_define_virtual_variable("$VERBOSE", verbose_getter, verbose_setter); + rb_define_virtual_variable("$-v", verbose_getter, verbose_setter); + rb_define_virtual_variable("$-w", verbose_getter, verbose_setter); + rb_define_virtual_variable("$-W", opt_W_getter, rb_gvar_readonly_setter); + rb_define_virtual_variable("$DEBUG", debug_getter, debug_setter); + rb_define_virtual_variable("$-d", debug_getter, debug_setter); + + rb_gvar_ractor_local("$VERBOSE"); + rb_gvar_ractor_local("$-v"); + rb_gvar_ractor_local("$-w"); + rb_gvar_ractor_local("$-W"); + rb_gvar_ractor_local("$DEBUG"); + rb_gvar_ractor_local("$-d"); rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0); rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0); diff --git a/vm.c b/vm.c index 879814a14b..ada33ae87b 100644 --- a/vm.c +++ b/vm.c @@ -3515,28 +3515,18 @@ Init_top_self(void) rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s"); } -static VALUE * -ruby_vm_verbose_ptr(rb_vm_t *vm) -{ - return &vm->verbose; -} - -static VALUE * -ruby_vm_debug_ptr(rb_vm_t *vm) -{ - return &vm->debug; -} - VALUE * rb_ruby_verbose_ptr(void) { - return ruby_vm_verbose_ptr(GET_VM()); + rb_ractor_t *cr = GET_RACTOR(); + return &cr->verbose; } VALUE * rb_ruby_debug_ptr(void) { - return ruby_vm_debug_ptr(GET_VM()); + rb_ractor_t *cr = GET_RACTOR(); + return &cr->debug; } /* iseq.c */ diff --git a/vm_core.h b/vm_core.h index f644e8a6bc..8525bfcf3e 100644 --- a/vm_core.h +++ b/vm_core.h @@ -633,7 +633,7 @@ typedef struct rb_vm_struct { struct list_head workqueue; /* <=> rb_workqueue_job.jnode */ rb_nativethread_lock_t workqueue_lock; - VALUE verbose, debug, orig_progname, progname; + VALUE orig_progname, progname; VALUE coverages; int coverage_mode;