[ruby/etc] Most Etc methods are not Ractor-safe currently

* See https://bugs.ruby-lang.org/issues/21115

https://github.com/ruby/etc/commit/ae62b7619c
This commit is contained in:
Benoit Daloze 2025-02-19 17:46:07 +01:00 committed by git
parent 0b186ed413
commit b9e9a1034a
2 changed files with 73 additions and 11 deletions

View File

@ -1163,14 +1163,27 @@ Init_etc(void)
{
VALUE mEtc;
#ifdef HAVE_RB_EXT_RACTOR_SAFE
RB_EXT_RACTOR_SAFE(true);
#endif
mEtc = rb_define_module("Etc");
/* The version */
rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION));
init_constants(mEtc);
/* Ractor-safe methods */
#ifdef HAVE_RB_EXT_RACTOR_SAFE
RB_EXT_RACTOR_SAFE(true);
#endif
rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
rb_define_module_function(mEtc, "uname", etc_uname, 0);
rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
/* Non-Ractor-safe methods, see https://bugs.ruby-lang.org/issues/21115 */
#ifdef HAVE_RB_EXT_RACTOR_SAFE
RB_EXT_RACTOR_SAFE(false);
#endif
rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
@ -1186,13 +1199,6 @@ Init_etc(void)
rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0);
rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
rb_define_module_function(mEtc, "uname", etc_uname, 0);
rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
sPasswd = rb_struct_define_under(mEtc, "Passwd",
"name",

View File

@ -173,7 +173,49 @@ class TestEtc < Test::Unit::TestCase
assert_operator(File, :absolute_path?, Etc.sysconfdir)
end if File.method_defined?(:absolute_path?)
def test_ractor
# All Ractor-safe methods should be tested here
def test_ractor_parallel
assert_ractor(<<~RUBY, require: 'etc')
20.times.map do
Ractor.new do
1000.times do
raise unless String === Etc.sysconfdir
raise unless String === Etc.systmpdir
raise unless Hash === Etc.uname
if defined?(Etc::SC_CLK_TCK)
raise unless Integer === Etc.sysconf(Etc::SC_CLK_TCK)
end
if defined?(Etc::CS_PATH)
raise unless String === Etc.confstr(Etc::CS_PATH)
end
if defined?(Etc::PC_PIPE_BUF)
IO.pipe { |r, w|
val = w.pathconf(Etc::PC_PIPE_BUF)
raise unless val.nil? || val.kind_of?(Integer)
}
end
raise unless Integer === Etc.nprocessors
end
end
end.each(&:take)
RUBY
end
def test_ractor_unsafe
assert_ractor(<<~RUBY, require: 'etc')
r = Ractor.new do
begin
Etc.passwd
rescue => e
e.class
end
end.take
assert_equal Ractor::UnsafeError, r
RUBY
end
def test_ractor_passwd
omit("https://bugs.ruby-lang.org/issues/21115")
return unless Etc.passwd # => skip test if no platform support
Etc.endpwent
@ -197,4 +239,18 @@ class TestEtc < Test::Unit::TestCase
assert_equal(name2, name)
RUBY
end
def test_ractor_getgrgid
omit("https://bugs.ruby-lang.org/issues/21115")
assert_ractor(<<~RUBY, require: 'etc')
20.times.map do
Ractor.new do
1000.times do
raise unless Etc.getgrgid(Process.gid).gid == Process.gid
end
end
end.each(&:take)
RUBY
end
end