Some global variables can be accessed from ractors

Some global variables should be used from non-main Ractors.
[Bug #17268]

```ruby
     # 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,
```
This commit is contained in:
Koichi Sasada 2020-10-20 10:46:43 +09:00
Родитель 9ced5fae6d
Коммит 99310e3eb5
11 изменённых файлов: 131 добавлений и 24 удалений

Просмотреть файл

@ -611,6 +611,65 @@ assert_equal 'ok', %q{
'ok' '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 # selfs are different objects
assert_equal 'false', %q{ assert_equal 'false', %q{
r = Ractor.new do r = Ractor.new do

Просмотреть файл

@ -10943,6 +10943,7 @@ re.$(OBJEXT): $(top_srcdir)/internal/imemo.h
re.$(OBJEXT): $(top_srcdir)/internal/re.h re.$(OBJEXT): $(top_srcdir)/internal/re.h
re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
re.$(OBJEXT): $(top_srcdir)/internal/string.h re.$(OBJEXT): $(top_srcdir)/internal/string.h
re.$(OBJEXT): $(top_srcdir)/internal/variable.h
re.$(OBJEXT): $(top_srcdir)/internal/warnings.h re.$(OBJEXT): $(top_srcdir)/internal/warnings.h
re.$(OBJEXT): {$(VPATH)}assert.h re.$(OBJEXT): {$(VPATH)}assert.h
re.$(OBJEXT): {$(VPATH)}backward/2/assume.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/stdalign.h
re.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h re.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
re.$(OBJEXT): {$(VPATH)}config.h re.$(OBJEXT): {$(VPATH)}config.h
re.$(OBJEXT): {$(VPATH)}constant.h
re.$(OBJEXT): {$(VPATH)}defines.h re.$(OBJEXT): {$(VPATH)}defines.h
re.$(OBJEXT): {$(VPATH)}encindex.h re.$(OBJEXT): {$(VPATH)}encindex.h
re.$(OBJEXT): {$(VPATH)}encoding.h re.$(OBJEXT): {$(VPATH)}encoding.h
re.$(OBJEXT): {$(VPATH)}id_table.h
re.$(OBJEXT): {$(VPATH)}intern.h re.$(OBJEXT): {$(VPATH)}intern.h
re.$(OBJEXT): {$(VPATH)}internal.h re.$(OBJEXT): {$(VPATH)}internal.h
re.$(OBJEXT): {$(VPATH)}internal/anyargs.h re.$(OBJEXT): {$(VPATH)}internal/anyargs.h

3
eval.c
Просмотреть файл

@ -2084,6 +2084,9 @@ Init_eval(void)
rb_define_virtual_variable("$@", errat_getter, errat_setter); rb_define_virtual_variable("$@", errat_getter, errat_setter);
rb_define_virtual_variable("$!", errinfo_getter, 0); 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("raise", f_raise, -1);
rb_define_global_function("fail", f_raise, -1); rb_define_global_function("fail", f_raise, -1);

3
io.c
Просмотреть файл

@ -13543,6 +13543,7 @@ Init_IO(void)
rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter); rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter);
rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE); 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, "initialize_copy", rb_io_init_copy, 1);
rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1); rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
@ -13764,6 +13765,8 @@ Init_IO(void)
ARGF.filename = rb_str_new2("-"); ARGF.filename = rb_str_new2("-");
rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set); 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); rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
#if defined (_WIN32) || defined(__CYGWIN__) #if defined (_WIN32) || defined(__CYGWIN__)

Просмотреть файл

@ -8445,6 +8445,10 @@ InitVM_process(void)
#define rb_intern(str) rb_intern_const(str) #define rb_intern(str) rb_intern_const(str)
rb_define_virtual_variable("$?", get_CHILD_STATUS, 0); rb_define_virtual_variable("$?", get_CHILD_STATUS, 0);
rb_define_virtual_variable("$$", get_PROCESS_ID, 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("exec", f_exec, -1);
rb_define_global_function("fork", rb_f_fork, 0); rb_define_global_function("fork", rb_f_fork, 0);
rb_define_global_function("exit!", rb_f_exit_bang, -1); rb_define_global_function("exit!", rb_f_exit_bang, -1);

Просмотреть файл

@ -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_stdout = rb_io_prep_stdout();
r->r_stderr = rb_io_prep_stderr(); 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_thread_create_ractor(r, args, block);
RB_GC_GUARD(rv); RB_GC_GUARD(rv);

Просмотреть файл

@ -125,6 +125,8 @@ struct rb_ractor_struct {
VALUE r_stdin; VALUE r_stdin;
VALUE r_stdout; VALUE r_stdout;
VALUE r_stderr; VALUE r_stderr;
VALUE verbose;
VALUE debug;
}; // rb_ractor_t is defined in vm_core.h }; // rb_ractor_t is defined in vm_core.h
rb_ractor_t *rb_ractor_main_alloc(void); rb_ractor_t *rb_ractor_main_alloc(void);

7
re.c
Просмотреть файл

@ -19,6 +19,7 @@
#include "internal/imemo.h" #include "internal/imemo.h"
#include "internal/re.h" #include "internal/re.h"
#include "internal/string.h" #include "internal/string.h"
#include "internal/variable.h"
#include "regint.h" #include "regint.h"
#include "ruby/encoding.h" #include "ruby/encoding.h"
#include "ruby/re.h" #include "ruby/re.h"
@ -4052,6 +4053,12 @@ Init_Regexp(void)
rb_define_virtual_variable("$'", postmatch_getter, 0); rb_define_virtual_variable("$'", postmatch_getter, 0);
rb_define_virtual_variable("$+", last_paren_match_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("$=", ignorecase_getter, ignorecase_setter);
rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter); rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter);
rb_define_virtual_variable("$-K", kcode_getter, kcode_setter); rb_define_virtual_variable("$-K", kcode_getter, kcode_setter);

50
ruby.c
Просмотреть файл

@ -63,6 +63,7 @@
#include "ruby/thread.h" #include "ruby/thread.h"
#include "ruby/util.h" #include "ruby/util.h"
#include "ruby/version.h" #include "ruby/version.h"
#include "ruby/internal/error.h"
#ifndef MAXPATHLEN #ifndef MAXPATHLEN
# define MAXPATHLEN 1024 # 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("$-l", opt->do_line);
rb_define_readonly_boolean("$-a", opt->do_split); 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) { if ((rb_e_script = opt->e_script) != 0) {
rb_gc_register_mark_object(opt->e_script); 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); 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 static void
verbose_setter(VALUE val, ID id, VALUE *variable) verbose_setter(VALUE val, ID id, VALUE *variable)
{ {
*variable = RTEST(val) ? Qtrue : val; *rb_ruby_verbose_ptr() = RTEST(val) ? Qtrue : val;
} }
static VALUE 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: case Qnil:
return INT2FIX(0); return INT2FIX(0);
case Qfalse: 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 */ /*! Defines built-in variables */
void void
ruby_prog_init(void) ruby_prog_init(void)
{ {
rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter); rb_define_virtual_variable("$VERBOSE", verbose_getter, verbose_setter);
rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter); rb_define_virtual_variable("$-v", verbose_getter, verbose_setter);
rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter); rb_define_virtual_variable("$-w", verbose_getter, verbose_setter);
rb_define_hooked_variable("$-W", &ruby_verbose, opt_W_getter, rb_gvar_readonly_setter); rb_define_virtual_variable("$-W", opt_W_getter, rb_gvar_readonly_setter);
rb_define_variable("$DEBUG", &ruby_debug); rb_define_virtual_variable("$DEBUG", debug_getter, debug_setter);
rb_define_variable("$-d", &ruby_debug); 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("$0", &rb_progname, 0, set_arg0);
rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0); rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);

18
vm.c
Просмотреть файл

@ -3515,28 +3515,18 @@ Init_top_self(void)
rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s"); 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 * VALUE *
rb_ruby_verbose_ptr(void) rb_ruby_verbose_ptr(void)
{ {
return ruby_vm_verbose_ptr(GET_VM()); rb_ractor_t *cr = GET_RACTOR();
return &cr->verbose;
} }
VALUE * VALUE *
rb_ruby_debug_ptr(void) rb_ruby_debug_ptr(void)
{ {
return ruby_vm_debug_ptr(GET_VM()); rb_ractor_t *cr = GET_RACTOR();
return &cr->debug;
} }
/* iseq.c */ /* iseq.c */

Просмотреть файл

@ -633,7 +633,7 @@ typedef struct rb_vm_struct {
struct list_head workqueue; /* <=> rb_workqueue_job.jnode */ struct list_head workqueue; /* <=> rb_workqueue_job.jnode */
rb_nativethread_lock_t workqueue_lock; rb_nativethread_lock_t workqueue_lock;
VALUE verbose, debug, orig_progname, progname; VALUE orig_progname, progname;
VALUE coverages; VALUE coverages;
int coverage_mode; int coverage_mode;