[#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:51148] [Ruby master Bug#18437] 3.1.0 install stucks on FreeBSD & NFS

From: "os (Shigeki OHARA)" <noreply@...>
Date: 2022-01-23 08:22:46 UTC
List: ruby-dev #51148
Issue #18437 has been updated by os (Shigeki OHARA).


I tried installing the latest development version of Ruby and RubyGems, and successfully completed it.

```
% rbenv install 3.2.0-dev
Cloning https://github.com/ruby/ruby.git...
Installing ruby-master...
Installed ruby-master to /home/XXXXXXXX/.rbenv-amd64-freebsd13/versions/3.2.0-dev

% rbenv local 3.2.0-dev
% ruby -v
ruby 3.2.0dev (2022-01-22T16:02:38Z master ab1aa90c32) [x86_64-freebsd13.0]
% ruby -rrubygems -e "p Gem::VERSION"
"3.4.0.dev"
%
```


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

* 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