[#51136] [Ruby master Bug#18489] Segmentation fault with ruby 3.1.0 in `active_decorator` — "t_mimura (Tomohiko Mimura)" <noreply@...>

Issue #18489 has been reported by t_mimura (Tomohiko Mimura).

11 messages 2022/01/14

[ruby-dev:51149] [Ruby master Bug#18437] 3.1.0 install stucks on FreeBSD & NFS

From: deivid <noreply@...>
Date: 2022-01-23 14:34:59 UTC
List: ruby-dev #51149
Issue #18437 has been updated by deivid (David Rodríguez).


That's great to hear. Yes, we fixed this differently by avoiding flock on non Windows platforms, since it didn't seem necessary and we were not using it in previous versions. But I think your patch might still bel valuable for Windows where `flock` seems necessary.

----------------------------------------
Bug #18437: 3.1.0 install stucks on FreeBSD & NFS
https://bugs.ruby-lang.org/issues/18437#change-96104

* Author: os (Shigeki OHARA)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-freebsd13.0]
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
## 概要

FreeBSD マシンで NFS 上のホームディレクトリーへ Ruby 3.1.0 を rbenv install 3.1.0 でインストールしようとすると、
gem のインストールで処理が止まってしまいます。

## 再現手順

### 環境

* OS (NFS クライアント): FreeBSD 13.0-RELEASE-p5
* NFS サーバー: CentOS 7.9
* NFSv4
* rbenv 1.2.0-6-g304cb7b, ruby-build 20211225-2-g927aec4

### 手順

```
% rbenv install 3.1.0
```

### 結果

10 数分待ってもインストールは終了せず。
このとき、 rbenv install のログは下記箇所で止まっています。

```
(snip...)

installing default gems from lib:   /home/XXXXXXXX/.rbenv-amd64-freebsd13/versions/3.1.0/lib/ruby/gems/3.1.0
                                    abbrev 0.1.0
```

その後、 C-c すると、下記トレースで終了します。

```
/tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems.rb:793:in `flock': Interrupt
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems.rb:793:in `block in open_with_flock'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems.rb:790:in `open'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems.rb:790:in `open_with_flock'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/stub_specification.rb:113:in `data'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/stub_specification.rb:203:in `valid?'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/specification.rb:778:in `select'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/specification.rb:778:in `gemspec_stubs_in'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/specification.rb:824:in `default_stubs'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/specification.rb:850:in `stubs_for_pattern'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/specification.rb:811:in `stubs'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/specification.rb:1085:in `latest_specs'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/specification.rb:1092:in `latest_spec_for'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/installer.rb:514:in `generate_plugins'
        from /tmp/ruby-build.20211227102425.80508.kNmLXp/ruby-3.1.0/lib/rubygems/installer.rb:324:in `install'
        from ./tool/rbinstall.rb:899:in `block in install'
        from ./tool/rbinstall.rb:713:in `no_write'
        from ./tool/rbinstall.rb:899:in `install'
        from ./tool/rbinstall.rb:1002:in `block in install_default_gem'
        from ./tool/rbinstall.rb:989:in `each'
        from ./tool/rbinstall.rb:989:in `install_default_gem'
        from ./tool/rbinstall.rb:927:in `block in <main>'
        from ./tool/rbinstall.rb:1127:in `block in <main>'
        from ./tool/rbinstall.rb:1124:in `each'
        from ./tool/rbinstall.rb:1124:in `<main>'
gmake: *** [uncommon.mk:383: do-install-all] 割り込み
```

下記サイトによると、 NFS 上の排他的ロックは書き込みできるモードでオープンする必要があるとのことなので、

* https://blog.tmtms.net/entry/2016/03/11/flock

下記のようなパッチを当てて試したところ、
rbenv install 3.1.0 が完遂するようになりました。

```
diff -ur ruby-3.1.0.orig/lib/rubygems/specification.rb ruby-3.1.0/lib/rubygems/specification.rb
--- ruby-3.1.0.orig/lib/rubygems/specification.rb       2021-12-25 21:23:14.000000000 +0900
+++ ruby-3.1.0/lib/rubygems/specification.rb    2021-12-27 12:21:31.756622831 +0900
@@ -1116,7 +1116,7 @@
     file = file.dup.tap(&Gem::UNTAINT)
     return unless File.file?(file)

-    code = Gem.open_with_flock(file, 'r:UTF-8:-', &:read)
+    code = Gem.open_with_flock(file, 'r+:UTF-8:-', &:read)

     code.tap(&Gem::UNTAINT)

diff -ur ruby-3.1.0.orig/lib/rubygems/stub_specification.rb ruby-3.1.0/lib/rubygems/stub_specification.rb
--- ruby-3.1.0.orig/lib/rubygems/stub_specification.rb  2021-12-25 21:23:14.000000000 +0900
+++ ruby-3.1.0/lib/rubygems/stub_specification.rb       2021-12-27 12:21:05.161104183 +0900
@@ -9,7 +9,7 @@
   PREFIX = "# stub: ".freeze

   # :nodoc:
-  OPEN_MODE = 'r:UTF-8:-'.freeze
+  OPEN_MODE = 'r+:UTF-8:-'.freeze

   class StubLine # :nodoc: all
     attr_reader :name, :version, :platform, :require_paths, :extensions,
```

先のサイトによると、読み込み専用で排他的ロックを掛けると、
Linux では EBADF になるようなのですが、
FreeBSD だとブロックするようです。

```
% cat locktest.rb
#!/usr/bin/env ruby
require "timeout"
filepath = ARGV.shift
File.open(filepath, "w").close  # just touch
File.open(filepath, "r") do |f|
  Timeout.timeout(3) do
    f.flock(File::LOCK_EX)
  end
end
% ruby locktest.rb /tmp/locktest.lock
% ruby locktest.rb ~/locktest.lock
Traceback (most recent call last):
        5: from locktest.rb:5:in `<main>'
        4: from locktest.rb:5:in `open'
        3: from locktest.rb:6:in `block in <main>'
        2: from /usr/local/lib/ruby/2.7/timeout.rb:110:in `timeout'
        1: from locktest.rb:7:in `block (2 levels) in <main>'
locktest.rb:7:in `flock': execution expired (Timeout::Error)
% 
```




-- 
https://bugs.ruby-lang.org/

In This Thread