Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 01401a7d24d8
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9217c6fbfc8d
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Aug 11, 2016

  1. Synchronize around getgrgid call. Fixes #4057.

    getgrgid is thread-safe on OS X, but other platforms are not
    required to be thread-safe by the POSIX specification. It appears
    that at least some flavors of Linux do not have thread-safe
    getgrgid. To aid users who might be calling it across threads, we
    lock around the native getgrgid call.
    
    I chose to lock around the RubyEtc.class to ensure the native call
    is single-threaded for all JRuby instances in a given classloader.
    There's no clean way to make that guarantee across classloaders.
    headius committed Aug 11, 2016
    Copy the full SHA
    64ab8ea View commit details
  2. Copy the full SHA
    9217c6f View commit details
Showing with 18 additions and 1 deletion.
  1. +8 −1 core/src/main/java/org/jruby/ext/etc/RubyEtc.java
  2. +10 −0 spec/ruby/library/etc/getgrgid_spec.rb
9 changes: 8 additions & 1 deletion core/src/main/java/org/jruby/ext/etc/RubyEtc.java
Original file line number Diff line number Diff line change
@@ -394,7 +394,14 @@ public static IRubyObject group(IRubyObject recv, Block block) {
public static IRubyObject getgrent(IRubyObject recv) {
Ruby runtime = recv.getRuntime();
try {
Group gr = runtime.getPosix().getgrent();
Group gr;

// We synchronize on this class so at least all JRuby instances in this classloader are safe.
// See jruby/jruby#4057
synchronized (RubyEtc.class) {
gr = runtime.getPosix().getgrent();
}

if (gr != null) {
return setupGroup(recv.getRuntime(), gr);
} else {
10 changes: 10 additions & 0 deletions spec/ruby/library/etc/getgrgid_spec.rb
Original file line number Diff line number Diff line change
@@ -56,5 +56,15 @@
lambda { Etc.getgrgid("foo") }.should raise_error(TypeError)
lambda { Etc.getgrgid(nil) }.should raise_error(TypeError)
end

it "can be called safely by multiple threads" do
20.times.map do
Thread.new do
100.times do
Etc.getgrgid(@gid).gid.should == @gid
end
end
end.each(&:join)
end
end
end