Skip to content

Commit ae62b76

Browse files
committed
Most Etc methods are not Ractor-safe currently
* See https://bugs.ruby-lang.org/issues/21115
1 parent eb33efe commit ae62b76

File tree

2 files changed

+73
-11
lines changed

2 files changed

+73
-11
lines changed

ext/etc/etc.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,14 +1163,27 @@ Init_etc(void)
11631163
{
11641164
VALUE mEtc;
11651165

1166-
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1167-
RB_EXT_RACTOR_SAFE(true);
1168-
#endif
11691166
mEtc = rb_define_module("Etc");
11701167
/* The version */
11711168
rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION));
11721169
init_constants(mEtc);
11731170

1171+
/* Ractor-safe methods */
1172+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1173+
RB_EXT_RACTOR_SAFE(true);
1174+
#endif
1175+
rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
1176+
rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
1177+
rb_define_module_function(mEtc, "uname", etc_uname, 0);
1178+
rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
1179+
rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
1180+
rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
1181+
rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
1182+
1183+
/* Non-Ractor-safe methods, see https://bugs.ruby-lang.org/issues/21115 */
1184+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1185+
RB_EXT_RACTOR_SAFE(false);
1186+
#endif
11741187
rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
11751188

11761189
rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
@@ -1186,13 +1199,6 @@ Init_etc(void)
11861199
rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0);
11871200
rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
11881201
rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
1189-
rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
1190-
rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
1191-
rb_define_module_function(mEtc, "uname", etc_uname, 0);
1192-
rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
1193-
rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
1194-
rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
1195-
rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
11961202

11971203
sPasswd = rb_struct_define_under(mEtc, "Passwd",
11981204
"name",

test/etc/test_etc.rb

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,49 @@ def test_sysconfdir
173173
assert_operator(File, :absolute_path?, Etc.sysconfdir)
174174
end if File.method_defined?(:absolute_path?)
175175

176-
def test_ractor
176+
# All Ractor-safe methods should be tested here
177+
def test_ractor_parallel
178+
assert_ractor(<<~RUBY, require: 'etc')
179+
20.times.map do
180+
Ractor.new do
181+
1000.times do
182+
raise unless String === Etc.sysconfdir
183+
raise unless String === Etc.systmpdir
184+
raise unless Hash === Etc.uname
185+
if defined?(Etc::SC_CLK_TCK)
186+
raise unless Integer === Etc.sysconf(Etc::SC_CLK_TCK)
187+
end
188+
if defined?(Etc::CS_PATH)
189+
raise unless String === Etc.confstr(Etc::CS_PATH)
190+
end
191+
if defined?(Etc::PC_PIPE_BUF)
192+
IO.pipe { |r, w|
193+
val = w.pathconf(Etc::PC_PIPE_BUF)
194+
raise unless val.nil? || val.kind_of?(Integer)
195+
}
196+
end
197+
raise unless Integer === Etc.nprocessors
198+
end
199+
end
200+
end.each(&:take)
201+
RUBY
202+
end
203+
204+
def test_ractor_unsafe
205+
assert_ractor(<<~RUBY, require: 'etc')
206+
r = Ractor.new do
207+
begin
208+
Etc.passwd
209+
rescue => e
210+
e.class
211+
end
212+
end.take
213+
assert_equal Ractor::UnsafeError, r
214+
RUBY
215+
end
216+
217+
def test_ractor_passwd
218+
omit("https://bugs.ruby-lang.org/issues/21115")
177219
return unless Etc.passwd # => skip test if no platform support
178220
Etc.endpwent
179221

@@ -197,4 +239,18 @@ def test_ractor
197239
assert_equal(name2, name)
198240
RUBY
199241
end
242+
243+
def test_ractor_getgrgid
244+
omit("https://bugs.ruby-lang.org/issues/21115")
245+
246+
assert_ractor(<<~RUBY, require: 'etc')
247+
20.times.map do
248+
Ractor.new do
249+
1000.times do
250+
raise unless Etc.getgrgid(Process.gid).gid == Process.gid
251+
end
252+
end
253+
end.each(&:take)
254+
RUBY
255+
end
200256
end

0 commit comments

Comments
 (0)