bootsnap 1.1.8 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a6f66d96dbadca08e5c50985c45319350f1e85ca
4
- data.tar.gz: c1227f8f8c6ed542abe582c221ccf45318655e87
2
+ SHA256:
3
+ metadata.gz: 40694ca2512ff7861584a4f9cee05e424c3d9319f3b36c7f4f45f9196d2d9f19
4
+ data.tar.gz: '087c4f2dafdd51a6a3d0a69d31aadabfe6ef90bf2ab12b861f2a288d7b16c04a'
5
5
  SHA512:
6
- metadata.gz: fa366476bf324d6eda9415e7170d67e31eb4a01d08758ff51d9e83c7661db8160cfa334ef9df67777ef059887de24a3f8a7da49b1675f3a1b0bf7704ecf42620
7
- data.tar.gz: '06758fb4f8445d041816330983799684a3b79e6ec82ac1e21cf087544d377744b0bb8bc20012146d529876fac6398e1053821eea2468be60c8194c6c07855312'
6
+ metadata.gz: ecbabde06c5f871702a000128e4dbc15d60fe0e16ab7adb4a8bb40b1c3b5b5f54b39c6927dc5aea9e49242d7e7f5deb596c42c44f8c2b8f998f835ec5b058b47
7
+ data.tar.gz: d566ffe7c3048f57c3c4fcd925d5e8ff5a722fc2622628e26571361e7a0fbdb5cbe8c724d45f2fc8ba09d0de614c5fad87f1875ecc99a08a34aab3afa7665fe1
data/.travis.yml CHANGED
@@ -1,4 +1,24 @@
1
1
  language: ruby
2
- rvm: ruby-2.4.1
3
- before_script: rake
4
- script: bin/testunit
2
+ sudo: false
3
+
4
+ os:
5
+ - linux
6
+ - osx
7
+
8
+ rvm:
9
+ - ruby-2.4
10
+ - ruby-2.5
11
+ - ruby-head
12
+
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: ruby-head
16
+ include:
17
+ - rvm: jruby
18
+ os: linux
19
+ env: MINIMAL_SUPPORT=1
20
+ - rvm: truffleruby
21
+ os: linux
22
+ env: MINIMAL_SUPPORT=1
23
+
24
+ script: bin/ci
data/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
+ # 1.4.0
2
+
3
+ * When running in development mode, always fall back to a full path scan on LoadError, making
4
+ bootsnap more able to detect newly-created files. (#230)
5
+ * Respect `$LOADED_FEATURES.delete` in order to support code reloading, for integration with
6
+ Zeitwerk. (#230)
7
+ * Minor performance improvement: flow-control exceptions no longer generate backtraces.
8
+ * Better support for requiring from environments where some features are not supported (especially
9
+ JRuby). (#226)k
10
+ * More robust handling of OS errors when creating files. (#225)
11
+
12
+ # 1.3.2
13
+
14
+ * Fix Spring + Bootsnap incompatibility when there are files with similar names.
15
+ * Fix `YAML.load_file` monkey patch to keep accepting File objects as arguments.
16
+ * Fix the API for `ActiveSupport::Dependencies#autoloadable_module?`.
17
+ * Some performance improvements.
18
+
19
+ # 1.3.1
20
+
21
+ * Change load path scanning to more correctly follow symlinks.
22
+
23
+ # 1.3.0
24
+
25
+ * Handle cases where load path entries are symlinked (https://github.com/Shopify/bootsnap/pull/136)
26
+
27
+ # 1.2.1
28
+
29
+ * Fix method visibility of `Kernel#require`.
30
+
31
+ # 1.2.0
32
+
33
+ * Add `LoadedFeaturesIndex` to preserve fix a common bug related to `LOAD_PATH` modifications after
34
+ loading bootsnap.
35
+
1
36
  # 1.1.8
2
37
 
3
38
  * Don't cache YAML documents with `!ruby/object`
data/README.jp.md ADDED
@@ -0,0 +1,231 @@
1
+ # Bootsnap [![Build Status](https://travis-ci.org/Shopify/bootsnap.svg?branch=master)](https://travis-ci.org/Shopify/bootsnap)
2
+
3
+ Bootsnap は RubyVM におけるバイトコード生成やファイルルックアップ等の時間のかかる処理を最適化するためのライブラリです。ActiveSupport や YAML もサポートしています。[内部動作](#内部動作)もご覧ください。
4
+
5
+ 注意書き: このライブラリは英語話者によって管理されています。この README は日本語ですが、日本語でのサポートはしておらず、リクエストにお答えすることもできません。バイリンガルの方がサポートをサポートしてくださる場合はお知らせください!:)
6
+
7
+ ### パフォーマンス
8
+
9
+ * [Discourse](https://github.com/discourse/discourse) では、約6秒から3秒まで、約50%の起動時間短縮が確認されています。
10
+ * 小さなアプリケーションでも、50%の改善(3.6秒から1.8秒)が確認されています。
11
+ * 非常に巨大でモノリシックなアプリである Shopify のプラットフォームでは、約25秒から6.5秒へと約75%短縮されました。
12
+
13
+ ## 使用方法
14
+
15
+ この gem は macOS と Linux で作動します。まずは、`bootsnap` を `Gemfile` に追加します:
16
+
17
+ ```ruby
18
+ gem 'bootsnap', require: false
19
+ ```
20
+
21
+ Rails を使用している場合は、以下のコードを、`config/boot.rb` 内にある `require 'bundler/setup'` の直後に追加してください。
22
+
23
+ ```ruby
24
+ require 'bootsnap/setup'
25
+ ```
26
+
27
+ 単に `gem 'bootsnap', require: 'bootsnap/setup'` と指定することも技術的には可能ですが、最大限のパフォーマンス改善を得るためには Bootsnap をできるだけ早く読み込むことが重要です。
28
+
29
+ この require の仕組みは[こちら](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/setup.rb)で確認できます。
30
+
31
+ Rails を使用していない場合、または、より多くの設定を変更したい場合は、以下のコードを `require 'bundler/setup'` の直後に追加してください(早く読み込まれるほど、より多くのものを最適化することができます)。
32
+
33
+ ```ruby
34
+ require 'bootsnap'
35
+ env = ENV['RAILS_ENV'] || "development"
36
+ Bootsnap.setup(
37
+  cache_dir:           'tmp/cache',         # キャッシュファイルを保存する path
38
+  development_mode:     env == 'development', # 現在の作業環境、例えば RACK_ENV, RAILS_ENV など。
39
+ load_path_cache: true, # キャッシュで LOAD_PATH を最適化する。
40
+  autoload_paths_cache: true,                 # キャッシュで ActiveSupport による autoload を行う。
41
+  disable_trace:       true,                 # (アルファ) `RubyVM::InstructionSequence.compile_option = { trace_instruction: false }`をセットする。
42
+  compile_cache_iseq:   true,                 # ISeq キャッシュをコンパイルする
43
+  compile_cache_yaml:   true                 # YAML キャッシュをコンパイルする
44
+ )
45
+ ```
46
+
47
+ **ヒント**: `require 'bootsnap'` を `BootLib::Require.from_gem('bootsnap', 'bootsnap')` で、 [こちらのトリック](https://github.com/Shopify/bootsnap/wiki/Bootlib::Require)を使って置き換えることができます。こうすると、巨大な`$LOAD_PATH`がある場合でも、起動時間を最短化するのに役立ちます。
48
+
49
+ 注意: Bootsnap と [Spring](https://github.com/rails/spring) は別領域の問題を扱うツールです。Bootsnap は個々のソースファイルの読み込みを高速化します。一方で、Spring は起動されたRailsプロセスのコピーを保持して次回の起動時に起動プロセスの一部を完全にスキップします。2つのツールはうまく連携しており、どちらも新しく生成された Rails アプリケーションにデフォルトで含まれています。
50
+
51
+ ### 環境
52
+ Bootsnapのすべての機能はセットアップ時の設定に従って開発、テスト、プロダクション、および他のすべての環境で有効化されます。Shopify では、この gem を問題なくすべての環境で安全に使用しています。
53
+
54
+ 特定の環境で機能を無効にする場合は、必要に応じて適切な ENV 変数または設定を考慮して設定を変更することをおすすめします。
55
+
56
+ ## 内部動作
57
+
58
+ Bootsnap は、処理に時間のかかるメソッドの結果をキャッシュすることで最適化しています。これは、大きく分けて2つのカテゴリに分けられます。
59
+
60
+ * [Path Pre-Scanning](#path-pre-scanning)
61
+ * `Kernel#require` と `Kernel#load` を `$LOAD_PATH` フルスキャンを行わないように変更します。
62
+ * `ActiveSupport::Dependencies.{autoloadable_module?,load_missing_constant,depend_on}` を `ActiveSupport::Dependencies.autoload_paths` のフルスキャンを行わないようにオーバーライドします。
63
+ * [Compilation caching](#compilation-caching)
64
+ * Ruby バイトコードのコンパイル結果をキャッシュするためのメソッド `RubyVM::InstructionSequence.load_iseq` が実装されています。
65
+ * `YAML.load_file` を YAML オブジェクトのロード結果を MessagePack でキャッシュするように変更します。 MessagePack でサポートされていないタイプが使われている場合は Marshal が使われます。
66
+
67
+ ### Path Pre-Scanning
68
+
69
+ _(このライブラリは [bootscale](https://github.com/byroot/bootscale) という別のライブラリを元に開発されました)_
70
+
71
+ Bootsnap の初期化時、あるいはパス(例えば、`$LOAD_PATH`)の変更時に、`Bootsnap::LoadPathCache` がキャッシュから必要なエントリーのリストを読み込みます。または、必要に応じてフルスキャンを実行し結果をキャッシュします。
72
+ その後、たとえば `require 'foo'` を評価する場合, Ruby は `$LOAD_PATH` `['x', 'y', ...]` のすべてのエントリーを繰り返し評価することで `x/foo.rb`, `y/foo.rb` などを探索します。これに対して Bootsnap は、キャッシュされた require 可能なファイルと `$LOAD_PATH` を見ることで、Rubyが最終的に選択するであろうパスで置き換えます。
73
+
74
+ この動作によって生成された syscall を見ると、最終的な結果は以前なら次のようになります。
75
+
76
+ ```
77
+ open x/foo.rb # (fail)
78
+ # (imagine this with 500 $LOAD_PATH entries instead of two)
79
+ open y/foo.rb # (success)
80
+ close y/foo.rb
81
+ open y/foo.rb
82
+ ...
83
+ ```
84
+
85
+ これが、次のようになります:
86
+
87
+ ```
88
+ open y/foo.rb
89
+ ...
90
+ ```
91
+
92
+ `autoload_paths_cache` オプションが `Bootsnap.setup` に与えられている場合、`ActiveSupport::Dependencies.autoload_paths` をトラバースする方法にはまったく同じ最適化が使用されます。
93
+
94
+ `*_path_cache` を機能させるオーバーライドを図にすると、次のようになります。
95
+
96
+ ![Bootsnapの説明図](https://cloud.githubusercontent.com/assets/3074765/24532120/eed94e64-158b-11e7-9137-438d759b2ac8.png)
97
+
98
+ Bootsnap は、 `$LOAD_PATH` エントリを安定エントリと不安定エントリの2つのカテゴリに分類します。不安定エントリはアプリケーションが起動するたびにスキャンされ、そのキャッシュは30秒間だけ有効になります。安定エントリーに期限切れはありません。コンテンツがスキャンされると、決して変更されないものとみなされます。
99
+
100
+ 安定していると考えられる唯一のディレクトリは、Rubyのインストールプレフィックス (`RbConfig::CONFIG['prefix']`, または `/usr/local/ruby` や `~/.rubies/x.y.z`)下にあるものと、`Gem.path` (たとえば `~/.gem/ruby/x.y.z`) や `Bundler.bundle_path` 下にあるものです。他のすべては不安定エントリと分類されます。
101
+
102
+ [`Bootsnap::LoadPathCache::Cache`](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/load_path_cache/cache.rb) に加えて次の図では、エントリの解決がどのように機能するかを理解するのに役立つかもしれません。経路探索は以下のようになります。
103
+
104
+ ![パス探索の仕組み](https://cloud.githubusercontent.com/assets/3074765/25388270/670b5652-299b-11e7-87fb-975647f68981.png)
105
+
106
+ また、`LoadError` のスキャンがどれほど重いかに注意を払うことも大切です。もし Ruby が `require 'something'` を評価し、そのファイルが `$LOAD_PATH` にない場合は、それを知るために `2 * $LOAD_PATH.length` のファイルシステムアスセスが必要になります。Bootsnap は、ファイルシステムにまったく触れずに `LoadError` を投げ、この結果をキャッシュします。
107
+
108
+ ## Compilation Caching
109
+
110
+ *(このコンセプトのより分かりやすい解説は [yomikomu](https://github.com/ko1/yomikomu) をお読み下さい。)*
111
+
112
+ Ruby には複雑な文法が実装されており、構文解析は簡単なオペレーションではありません。1.9以降、Ruby は Ruby ソースを内部のバイトコードに変換した後、Ruby VM によって実行してきました。2.3.0 以降、[RubyはAPIを公開し](https://ruby-doc.org/core-2.3.0/RubyVM/InstructionSequence.html)、そのバイトコードをキャッシュすることができるようになりました。これにより、同じファイルが複数ロードされた時の、比較的時間のかかる部分をバイパスすることができます。
113
+
114
+ また、アプリケーションの起動時に YAML ドキュメントの読み込みに多くの時間を費やしていることを発見しました。そして、 MessagePack と Marshal は deserialization にあたって YAML よりもはるかに高速であるということに気付きました。そこで、YAML ドキュメントを、Ruby バイトコードと同じコンパイルキャッシングの最適化を施すことで、高速化しています。Ruby の "バイトコード" フォーマットに相当するものは MessagePack ドキュメント (あるいは、MessagePack をサポートしていないタイプの YAML ドキュメントの場合は、Marshal stream)になります。
115
+
116
+ これらのコンパイル結果は、入力ファイル(FNV1a-64)のフルパスのハッシュを取って生成されたファイル名で、キャッシュディレクトリに保存されます。
117
+
118
+ Bootsnap 無しでは、ファイルを `require` するために生成された syscall の順序は次のようになっていました:
119
+
120
+ ```
121
+ open /c/foo.rb -> m
122
+ fstat64 m
123
+ close m
124
+ open /c/foo.rb -> o
125
+ fstat64 o
126
+ fstat64 o
127
+ read o
128
+ read o
129
+ ...
130
+ close o
131
+ ```
132
+
133
+ しかし Bootsnap では、次のようになります:
134
+
135
+ ```
136
+ open /c/foo.rb -> n
137
+ fstat64 n
138
+ close n
139
+ open /c/foo.rb -> n
140
+ fstat64 n
141
+ open (cache) -> m
142
+ read m
143
+ read m
144
+ close m
145
+ close n
146
+ ```
147
+
148
+ これは一見劣化していると思われるかもしれませんが、性能に大きな違いがあります。
149
+
150
+ *(両方のリストの最初の3つの syscalls -- `open`, `fstat64`, `close` -- は本質的に有用ではありません。[このRubyパッチ](https://bugs.ruby-lang.org/issues/13378)は、Boosnap と組み合わせることによって、それらを最適化しています)*
151
+
152
+ Bootsnap は、64バイトのヘッダーとそれに続くキャッシュの内容を含んだキャッシュファイルを書き込みます。ヘッダーは、次のいくつかのフィールドで構成されるキャッシュキーです。
153
+
154
+ - `version`、Bootsnapにハードコードされる基本的なスキーマのバージョン
155
+ - `os_version`、(macOS, BSDの) 現在のカーネルバージョンか 、(Linuxの) glibc のバージョンのハッシュ
156
+ - `compile_option`、`RubyVM::InstructionSequence.compile_option` の返り値
157
+ - `ruby_revision`、コンパイルされたRubyのバージョン
158
+ - `size`、ソースファイルのサイズ
159
+ - `mtime`、コンパイル時のソースファイルの最終変更タイムスタンプ
160
+ - `data_size`、バッファに読み込む必要のあるヘッダーに続くバイト数。
161
+
162
+ キーが有効な場合、キャッシュがファイルからロードされます。そうでない場合、キャッシュは再生成され、現在のキャッシュを破棄します。
163
+
164
+ # 最終的なキャッシュ結果
165
+
166
+ 次のファイル構造があるとします。
167
+
168
+ ```
169
+ /
170
+ ├── a
171
+ ├── b
172
+ └── c
173
+ └── foo.rb
174
+ ```
175
+
176
+ そして、このような `$LOAD_PATH` があるとします。
177
+
178
+ ```
179
+ ["/a", "/b", "/c"]
180
+ ```
181
+
182
+ Bootsnap なしで `require 'foo'` を呼び出すと、Ruby は次の順序で syscalls を生成します:
183
+
184
+ ```
185
+ open /a/foo.rb -> -1
186
+ open /b/foo.rb -> -1
187
+ open /c/foo.rb -> n
188
+ close n
189
+ open /c/foo.rb -> m
190
+ fstat64 m
191
+ close m
192
+ open /c/foo.rb -> o
193
+ fstat64 o
194
+ fstat64 o
195
+ read o
196
+ read o
197
+ ...
198
+ close o
199
+ ```
200
+
201
+ しかし Bootsnap では、次のようになります:
202
+
203
+ ```
204
+ open /c/foo.rb -> n
205
+ fstat64 n
206
+ close n
207
+ open /c/foo.rb -> n
208
+ fstat64 n
209
+ open (cache) -> m
210
+ read m
211
+ read m
212
+ close m
213
+ close n
214
+ ```
215
+
216
+ Bootsnap なしで `require 'nope'` を呼び出すと、次のようになります:
217
+
218
+ ```
219
+ open /a/nope.rb -> -1
220
+ open /b/nope.rb -> -1
221
+ open /c/nope.rb -> -1
222
+ open /a/nope.bundle -> -1
223
+ open /b/nope.bundle -> -1
224
+ open /c/nope.bundle -> -1
225
+ ```
226
+
227
+ ...そして、Bootsnap で `require 'nope'` を呼び出すと、次のようになります...
228
+
229
+ ```
230
+ # (nothing!)
231
+ ```
data/README.md CHANGED
@@ -10,7 +10,7 @@ to optimize and cache expensive computations. See [How Does This Work](#how-does
10
10
 
11
11
  ## Usage
12
12
 
13
- This gem works on MacOS and Linux.
13
+ This gem works on macOS and Linux.
14
14
 
15
15
  Add `bootsnap` to your `Gemfile`:
16
16
 
@@ -24,6 +24,9 @@ If you are using Rails, add this to `config/boot.rb` immediately after `require
24
24
  require 'bootsnap/setup'
25
25
  ```
26
26
 
27
+ It's technically possible to simply specify `gem 'bootsnap', require: 'bootsnap/setup'`, but it's
28
+ important to load Bootsnap as early as possible to get maximum performance improvement.
29
+
27
30
  You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/setup.rb).
28
31
 
29
32
  If you are not using Rails, or if you are but want more control over things, add this to your
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
- require 'rake/extensiontask'
1
+ require('rake/extensiontask')
2
+ require('bundler/gem_tasks')
2
3
 
3
4
  gemspec = Gem::Specification.load('bootsnap.gemspec')
4
5
  Rake::ExtensionTask.new do |ext|
data/bin/ci ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ set -euxo pipefail
4
+
5
+ if [[ "${MINIMAL_SUPPORT-0}" -eq 1 ]]; then
6
+ exec bin/test-minimal-support
7
+ else
8
+ rake
9
+ exec bin/testunit
10
+ fi
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "bootsnap"
3
+ require("bundler/setup")
4
+ require("bootsnap")
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "bootsnap"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require("irb")
14
14
  IRB.start(__FILE__)
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+
3
+ set -euxo pipefail
4
+
5
+ cd test/minimal_support
6
+ bundle
7
+ BOOTSNAP_CACHE_DIR=/tmp bundle exec ruby -w -I ../../lib bootsnap_setup.rb
data/bootsnap.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'bootsnap/version'
4
+ require('bootsnap/version')
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "bootsnap"
@@ -15,10 +15,16 @@ Gem::Specification.new do |spec|
15
15
  spec.description = spec.summary
16
16
  spec.homepage = "https://github.com/Shopify/bootsnap"
17
17
 
18
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ spec.metadata = {
19
+ 'bug_tracker_uri' => 'https://github.com/Shopify/bootsnap/issues',
20
+ 'changelog_uri' => 'https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md',
21
+ 'source_code_uri' => 'https://github.com/Shopify/bootsnap',
22
+ }
23
+
24
+ spec.files = %x(git ls-files -z).split("\x0").reject do |f|
19
25
  f.match(%r{^(test|spec|features)/})
20
26
  end
21
- spec.require_paths = ["lib"]
27
+ spec.require_paths = %w(lib)
22
28
 
23
29
  spec.required_ruby_version = '>= 2.0.0'
24
30
 
@@ -29,11 +35,11 @@ Gem::Specification.new do |spec|
29
35
  spec.extensions = ['ext/bootsnap/extconf.rb']
30
36
  end
31
37
 
32
- spec.add_development_dependency "bundler", '~> 1'
33
- spec.add_development_dependency 'rake', '~> 10.0'
34
- spec.add_development_dependency 'rake-compiler', '~> 0'
35
- spec.add_development_dependency "minitest", "~> 5.0"
36
- spec.add_development_dependency "mocha", "~> 1.2"
38
+ spec.add_development_dependency("bundler")
39
+ spec.add_development_dependency('rake', '~> 10.0')
40
+ spec.add_development_dependency('rake-compiler', '~> 0')
41
+ spec.add_development_dependency("minitest", "~> 5.0")
42
+ spec.add_development_dependency("mocha", "~> 1.2")
37
43
 
38
- spec.add_runtime_dependency "msgpack", "~> 1.0"
44
+ spec.add_runtime_dependency("msgpack", "~> 1.0")
39
45
  end
data/dev.yml CHANGED
@@ -2,7 +2,7 @@ env:
2
2
  BOOTSNAP_PEDANTIC: '1'
3
3
 
4
4
  up:
5
- - ruby: 2.3.3
5
+ - ruby: 2.6.0
6
6
  - bundler
7
7
  commands:
8
8
  build: rake compile
@@ -94,7 +94,6 @@ static int cache_key_equal(struct bs_cache_key * k1, struct bs_cache_key * k2);
94
94
  static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler);
95
95
  static int open_current_file(char * path, struct bs_cache_key * key, char ** errno_provenance);
96
96
  static int fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data, int * exception_tag, char ** errno_provenance);
97
- static VALUE prot_exception_for_errno(VALUE err);
98
97
  static uint32_t get_ruby_platform(void);
99
98
 
100
99
  /*
@@ -270,6 +269,8 @@ cache_key_equal(struct bs_cache_key * k1, struct bs_cache_key * k2)
270
269
  static VALUE
271
270
  bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
272
271
  {
272
+ FilePathValue(path_v);
273
+
273
274
  Check_Type(cachedir_v, T_STRING);
274
275
  Check_Type(path_v, T_STRING);
275
276
 
@@ -520,22 +521,6 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, char
520
521
  return ret;
521
522
  }
522
523
 
523
- /*
524
- * Given an errno value (converted to a ruby Fixnum), return the corresponding
525
- * Errno::* constant. If none is found, return StandardError instead.
526
- */
527
- static VALUE
528
- prot_exception_for_errno(VALUE err)
529
- {
530
- if (err != INT2FIX(0)) {
531
- VALUE mErrno = rb_const_get(rb_cObject, rb_intern("Errno"));
532
- VALUE constants = rb_funcall(mErrno, rb_intern("constants"), 0);
533
- VALUE which = rb_funcall(constants, rb_intern("[]"), 1, err);
534
- return rb_funcall(mErrno, rb_intern("const_get"), 1, which);
535
- }
536
- return rb_eStandardError;
537
- }
538
-
539
524
 
540
525
  /* Read contents from an fd, whose contents are asserted to be +size+ bytes
541
526
  * long, into a buffer */
@@ -689,11 +674,7 @@ succeed:
689
674
  return output_data;
690
675
  fail_errno:
691
676
  CLEANUP;
692
- exception = rb_protect(prot_exception_for_errno, INT2FIX(errno), &res);
693
- if (res) exception = rb_eStandardError;
694
- if (errno_provenance != NULL) {
695
- exception = rb_exc_new_str(exception, rb_str_new2(errno_provenance));
696
- }
677
+ exception = rb_syserr_new(errno, errno_provenance);
697
678
  rb_exc_raise(exception);
698
679
  __builtin_unreachable();
699
680
  raise: