Actions
Bug #18437
closed3.1.0 install stucks on FreeBSD & NFS
Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-freebsd13.0]
Description
概要¶
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 上の排他的ロックは書き込みできるモードでオープンする必要があるとのことなので、
下記のようなパッチを当てて試したところ、
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)
%
Actions
Like0
Like0Like0Like0Like0Like0