bootsnap 1.7.0 → 1.7.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/ext/bootsnap/bootsnap.c +31 -17
- data/ext/bootsnap/extconf.rb +19 -14
- data/lib/bootsnap.rb +13 -3
- data/lib/bootsnap/compile_cache/yaml.rb +37 -17
- data/lib/bootsnap/load_path_cache/cache.rb +26 -9
- data/lib/bootsnap/load_path_cache/loaded_features_index.rb +1 -1
- data/lib/bootsnap/load_path_cache/path_scanner.rb +14 -3
- data/lib/bootsnap/load_path_cache/store.rb +16 -9
- data/lib/bootsnap/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5f10210480d5f0c9574fe970766d9ef4799e9a8a212f6ccafab6a61c2189481
|
4
|
+
data.tar.gz: 3502a4a6f2ab2614f470d1aaa4d648ec86ab0aebe9390074a71fc1b7544a9d1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53975108838cdfe27d2b8c9e7b0ef1a25100e85ad691063d2dfd35e6db600bf5c76591aeaf51117651fab7c96779c6877a86984bfa97eb7152afecbd42d77828
|
7
|
+
data.tar.gz: 294d0cf74421f374dfde4bc551cdcb3a4f6dd4a971c0d50f3f03eb59c73ae75554689077af0cdc85aa7765aa8944e8e3edd919380fcfea9742bf7391d54756a8
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 1.7.4
|
4
|
+
|
5
|
+
* Stop raising errors when encoutering various file system errors. The cache is now best effort,
|
6
|
+
if somehow it can't be saved, bootsnapp will gracefully fallback to the original operation (e.g. `Kernel.require`).
|
7
|
+
(#353, #177, #262)
|
8
|
+
|
9
|
+
# 1.7.3
|
10
|
+
|
11
|
+
* Disable YAML precompilation when encountering YAML tags. (#351)
|
12
|
+
|
13
|
+
# 1.7.2
|
14
|
+
|
15
|
+
* Fix compatibility with msgpack < 1. (#349)
|
16
|
+
|
17
|
+
# 1.7.1
|
18
|
+
|
19
|
+
* Warn Ruby 2.5 users if they turn ISeq caching on. (#327, #244)
|
20
|
+
* Disable ISeq caching for the whole 2.5.x series again.
|
21
|
+
* Better handle hashing of Ruby strings. (#318)
|
22
|
+
|
3
23
|
# 1.7.0
|
4
24
|
|
5
25
|
* Fix detection of YAML files in gems.
|
data/ext/bootsnap/bootsnap.c
CHANGED
@@ -105,8 +105,7 @@ static VALUE bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handl
|
|
105
105
|
static VALUE bs_rb_precompile(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler);
|
106
106
|
|
107
107
|
/* Helpers */
|
108
|
-
static
|
109
|
-
static void bs_cache_path(const char * cachedir, const char * path, char (* cache_path)[MAX_CACHEPATH_SIZE]);
|
108
|
+
static void bs_cache_path(const char * cachedir, const VALUE path, char (* cache_path)[MAX_CACHEPATH_SIZE]);
|
110
109
|
static int bs_read_key(int fd, struct bs_cache_key * key);
|
111
110
|
static int cache_key_equal(struct bs_cache_key * k1, struct bs_cache_key * k2);
|
112
111
|
static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args);
|
@@ -211,7 +210,7 @@ bs_compile_option_crc32_set(VALUE self, VALUE crc32_v)
|
|
211
210
|
* - 32 bits doesn't feel collision-resistant enough; 64 is nice.
|
212
211
|
*/
|
213
212
|
static uint64_t
|
214
|
-
|
213
|
+
fnv1a_64_iter_cstr(uint64_t h, const char *str)
|
215
214
|
{
|
216
215
|
unsigned char *s = (unsigned char *)str;
|
217
216
|
|
@@ -224,7 +223,21 @@ fnv1a_64_iter(uint64_t h, const char *str)
|
|
224
223
|
}
|
225
224
|
|
226
225
|
static uint64_t
|
227
|
-
|
226
|
+
fnv1a_64_iter(uint64_t h, const VALUE str)
|
227
|
+
{
|
228
|
+
unsigned char *s = (unsigned char *)RSTRING_PTR(str);
|
229
|
+
unsigned char *str_end = (unsigned char *)RSTRING_PTR(str) + RSTRING_LEN(str);
|
230
|
+
|
231
|
+
while (s < str_end) {
|
232
|
+
h ^= (uint64_t)*s++;
|
233
|
+
h += (h << 1) + (h << 4) + (h << 5) + (h << 7) + (h << 8) + (h << 40);
|
234
|
+
}
|
235
|
+
|
236
|
+
return h;
|
237
|
+
}
|
238
|
+
|
239
|
+
static uint64_t
|
240
|
+
fnv1a_64(const VALUE str)
|
228
241
|
{
|
229
242
|
uint64_t h = (uint64_t)0xcbf29ce484222325ULL;
|
230
243
|
return fnv1a_64_iter(h, str);
|
@@ -245,7 +258,7 @@ get_ruby_revision(void)
|
|
245
258
|
} else {
|
246
259
|
uint64_t hash;
|
247
260
|
|
248
|
-
hash = fnv1a_64(
|
261
|
+
hash = fnv1a_64(ruby_revision);
|
249
262
|
return (uint32_t)(hash >> 32);
|
250
263
|
}
|
251
264
|
}
|
@@ -265,19 +278,19 @@ get_ruby_platform(void)
|
|
265
278
|
VALUE ruby_platform;
|
266
279
|
|
267
280
|
ruby_platform = rb_const_get(rb_cObject, rb_intern("RUBY_PLATFORM"));
|
268
|
-
hash = fnv1a_64(
|
281
|
+
hash = fnv1a_64(ruby_platform);
|
269
282
|
|
270
283
|
#ifdef _WIN32
|
271
284
|
return (uint32_t)(hash >> 32) ^ (uint32_t)GetVersion();
|
272
285
|
#elif defined(__GLIBC__)
|
273
|
-
hash =
|
286
|
+
hash = fnv1a_64_iter_cstr(hash, gnu_get_libc_version());
|
274
287
|
return (uint32_t)(hash >> 32);
|
275
288
|
#else
|
276
289
|
struct utsname utsname;
|
277
290
|
|
278
291
|
/* Not worth crashing if this fails; lose extra cache invalidation potential */
|
279
292
|
if (uname(&utsname) >= 0) {
|
280
|
-
hash =
|
293
|
+
hash = fnv1a_64_iter_cstr(hash, utsname.version);
|
281
294
|
}
|
282
295
|
|
283
296
|
return (uint32_t)(hash >> 32);
|
@@ -292,13 +305,13 @@ get_ruby_platform(void)
|
|
292
305
|
* The path will look something like: <cachedir>/12/34567890abcdef
|
293
306
|
*/
|
294
307
|
static void
|
295
|
-
bs_cache_path(const char * cachedir, const
|
308
|
+
bs_cache_path(const char * cachedir, const VALUE path, char (* cache_path)[MAX_CACHEPATH_SIZE])
|
296
309
|
{
|
297
310
|
uint64_t hash = fnv1a_64(path);
|
298
311
|
uint8_t first_byte = (hash >> (64 - 8));
|
299
312
|
uint64_t remainder = hash & 0x00ffffffffffffff;
|
300
313
|
|
301
|
-
sprintf(*cache_path, "%s/%
|
314
|
+
sprintf(*cache_path, "%s/%02"PRIx8"/%014"PRIx64, cachedir, first_byte, remainder);
|
302
315
|
}
|
303
316
|
|
304
317
|
/*
|
@@ -344,7 +357,7 @@ bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler, VALUE arg
|
|
344
357
|
char cache_path[MAX_CACHEPATH_SIZE];
|
345
358
|
|
346
359
|
/* generate cache path to cache_path */
|
347
|
-
bs_cache_path(cachedir,
|
360
|
+
bs_cache_path(cachedir, path_v, &cache_path);
|
348
361
|
|
349
362
|
return bs_fetch(path, path_v, cache_path, handler, args);
|
350
363
|
}
|
@@ -371,7 +384,7 @@ bs_rb_precompile(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
|
|
371
384
|
char cache_path[MAX_CACHEPATH_SIZE];
|
372
385
|
|
373
386
|
/* generate cache path to cache_path */
|
374
|
-
bs_cache_path(cachedir,
|
387
|
+
bs_cache_path(cachedir, path_v, &cache_path);
|
375
388
|
|
376
389
|
return bs_precompile(path, path_v, cache_path, handler);
|
377
390
|
}
|
@@ -451,8 +464,7 @@ open_cache_file(const char * path, struct bs_cache_key * key, const char ** errn
|
|
451
464
|
fd = open(path, O_RDONLY);
|
452
465
|
if (fd < 0) {
|
453
466
|
*errno_provenance = "bs_fetch:open_cache_file:open";
|
454
|
-
|
455
|
-
return ERROR_WITH_ERRNO;
|
467
|
+
return CACHE_MISS;
|
456
468
|
}
|
457
469
|
#ifdef _WIN32
|
458
470
|
setmode(fd, O_BINARY);
|
@@ -750,9 +762,11 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
750
762
|
/* If storage_data isn't a string, we can't cache it */
|
751
763
|
if (!RB_TYPE_P(storage_data, T_STRING)) goto invalid_type_storage_data;
|
752
764
|
|
753
|
-
/*
|
754
|
-
|
755
|
-
|
765
|
+
/* Attempt to write the cache key and storage_data to the cache directory.
|
766
|
+
* We do however ignore any failures to persist the cache, as it's better
|
767
|
+
* to move along, than to interrupt the process.
|
768
|
+
*/
|
769
|
+
atomic_write_cache_file(cache_path, ¤t_key, storage_data, &errno_provenance);
|
756
770
|
|
757
771
|
/* Having written the cache, now convert storage_data to output_data */
|
758
772
|
exception_tag = bs_storage_to_output(handler, args, storage_data, &output_data);
|
data/ext/bootsnap/extconf.rb
CHANGED
@@ -1,19 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require("mkmf")
|
3
|
-
$CFLAGS << ' -O3 '
|
4
|
-
$CFLAGS << ' -std=c99'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
$CFLAGS << ' -Wall'
|
10
|
-
$CFLAGS << ' -Werror'
|
11
|
-
$CFLAGS << ' -Wextra'
|
12
|
-
$CFLAGS << ' -Wpedantic'
|
4
|
+
if RUBY_ENGINE == 'ruby'
|
5
|
+
$CFLAGS << ' -O3 '
|
6
|
+
$CFLAGS << ' -std=c99'
|
13
7
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
# ruby.h has some -Wpedantic fails in some cases
|
9
|
+
# (e.g. https://github.com/Shopify/bootsnap/issues/15)
|
10
|
+
unless ['0', '', nil].include?(ENV['BOOTSNAP_PEDANTIC'])
|
11
|
+
$CFLAGS << ' -Wall'
|
12
|
+
$CFLAGS << ' -Werror'
|
13
|
+
$CFLAGS << ' -Wextra'
|
14
|
+
$CFLAGS << ' -Wpedantic'
|
15
|
+
|
16
|
+
$CFLAGS << ' -Wno-unused-parameter' # VALUE self has to be there but we don't care what it is.
|
17
|
+
$CFLAGS << ' -Wno-keyword-macro' # hiding return
|
18
|
+
$CFLAGS << ' -Wno-gcc-compat' # ruby.h 2.6.0 on macos 10.14, dunno
|
19
|
+
end
|
18
20
|
|
19
|
-
create_makefile("bootsnap/bootsnap")
|
21
|
+
create_makefile("bootsnap/bootsnap")
|
22
|
+
else
|
23
|
+
File.write("Makefile", dummy_makefile($srcdir).join(""))
|
24
|
+
end
|
data/lib/bootsnap.rb
CHANGED
@@ -54,6 +54,11 @@ module Bootsnap
|
|
54
54
|
"If you use Ruby 2.5 or newer this option is useless, if not upgrading is recommended."
|
55
55
|
end
|
56
56
|
|
57
|
+
if compile_cache_iseq && !iseq_cache_supported?
|
58
|
+
warn "Ruby 2.5 has a bug that break code tracing when code is loaded from cache. It is recommened " \
|
59
|
+
"to turn `compile_cache_iseq` off on Ruby 2.5"
|
60
|
+
end
|
61
|
+
|
57
62
|
Bootsnap::LoadPathCache.setup(
|
58
63
|
cache_path: cache_dir + '/bootsnap/load-path-cache',
|
59
64
|
development_mode: development_mode,
|
@@ -66,6 +71,13 @@ module Bootsnap
|
|
66
71
|
)
|
67
72
|
end
|
68
73
|
|
74
|
+
def self.iseq_cache_supported?
|
75
|
+
return @iseq_cache_supported if defined? @iseq_cache_supported
|
76
|
+
|
77
|
+
ruby_version = Gem::Version.new(RUBY_VERSION)
|
78
|
+
@iseq_cache_supported = ruby_version < Gem::Version.new('2.5.0') || ruby_version >= Gem::Version.new('2.6.0')
|
79
|
+
end
|
80
|
+
|
69
81
|
def self.default_setup
|
70
82
|
env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV']
|
71
83
|
development_mode = ['', nil, 'development'].include?(env)
|
@@ -92,14 +104,12 @@ module Bootsnap
|
|
92
104
|
cache_dir = File.join(app_root, 'tmp', 'cache')
|
93
105
|
end
|
94
106
|
|
95
|
-
ruby_version = Gem::Version.new(RUBY_VERSION)
|
96
|
-
iseq_cache_enabled = ruby_version < Gem::Version.new('2.5.0') || ruby_version >= Gem::Version.new('2.5.4')
|
97
107
|
|
98
108
|
setup(
|
99
109
|
cache_dir: cache_dir,
|
100
110
|
development_mode: development_mode,
|
101
111
|
load_path_cache: !ENV['DISABLE_BOOTSNAP_LOAD_PATH_CACHE'],
|
102
|
-
compile_cache_iseq: !ENV['DISABLE_BOOTSNAP_COMPILE_CACHE'] &&
|
112
|
+
compile_cache_iseq: !ENV['DISABLE_BOOTSNAP_COMPILE_CACHE'] && iseq_cache_supported?,
|
103
113
|
compile_cache_yaml: !ENV['DISABLE_BOOTSNAP_COMPILE_CACHE'],
|
104
114
|
)
|
105
115
|
|
@@ -8,8 +8,7 @@ module Bootsnap
|
|
8
8
|
attr_accessor(:msgpack_factory, :cache_dir, :supported_options)
|
9
9
|
|
10
10
|
def input_to_storage(contents, _)
|
11
|
-
|
12
|
-
obj = ::YAML.load(contents)
|
11
|
+
obj = strict_load(contents)
|
13
12
|
msgpack_factory.dump(obj)
|
14
13
|
rescue NoMethodError, RangeError
|
15
14
|
# The object included things that we can't serialize
|
@@ -27,6 +26,13 @@ module Bootsnap
|
|
27
26
|
::YAML.load(data, **(kwargs || {}))
|
28
27
|
end
|
29
28
|
|
29
|
+
def strict_load(payload, *args)
|
30
|
+
ast = ::YAML.parse(payload)
|
31
|
+
return ast unless ast
|
32
|
+
strict_visitor.create(*args).visit(ast)
|
33
|
+
end
|
34
|
+
ruby2_keywords :strict_load if respond_to?(:ruby2_keywords, true)
|
35
|
+
|
30
36
|
def precompile(path, cache_dir: YAML.cache_dir)
|
31
37
|
Bootsnap::CompileCache::Native.precompile(
|
32
38
|
cache_dir,
|
@@ -51,22 +57,25 @@ module Bootsnap
|
|
51
57
|
# see: https://github.com/msgpack/msgpack-ruby/pull/122
|
52
58
|
factory = MessagePack::Factory.new
|
53
59
|
factory.register_type(0x00, Symbol)
|
54
|
-
factory.register_type(
|
55
|
-
MessagePack::Timestamp::TYPE, # or just -1
|
56
|
-
Time,
|
57
|
-
packer: MessagePack::Time::Packer,
|
58
|
-
unpacker: MessagePack::Time::Unpacker
|
59
|
-
)
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
61
|
+
if defined? MessagePack::Timestamp
|
62
|
+
factory.register_type(
|
63
|
+
MessagePack::Timestamp::TYPE, # or just -1
|
64
|
+
Time,
|
65
|
+
packer: MessagePack::Time::Packer,
|
66
|
+
unpacker: MessagePack::Time::Unpacker
|
67
|
+
)
|
68
|
+
|
69
|
+
marshal_fallback = {
|
70
|
+
packer: ->(value) { Marshal.dump(value) },
|
71
|
+
unpacker: ->(payload) { Marshal.load(payload) },
|
72
|
+
}
|
73
|
+
{
|
74
|
+
Date => 0x01,
|
75
|
+
Regexp => 0x02,
|
76
|
+
}.each do |type, code|
|
77
|
+
factory.register_type(code, type, marshal_fallback)
|
78
|
+
end
|
70
79
|
end
|
71
80
|
|
72
81
|
self.msgpack_factory = factory
|
@@ -83,6 +92,17 @@ module Bootsnap
|
|
83
92
|
end
|
84
93
|
self.supported_options.freeze
|
85
94
|
end
|
95
|
+
|
96
|
+
def strict_visitor
|
97
|
+
self::NoTagsVisitor ||= Class.new(Psych::Visitors::ToRuby) do
|
98
|
+
def visit(target)
|
99
|
+
if target.tag
|
100
|
+
raise Uncompilable, "YAML tags are not supported: #{target.tag}"
|
101
|
+
end
|
102
|
+
super
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
86
106
|
end
|
87
107
|
|
88
108
|
module Patch
|
@@ -10,8 +10,8 @@ module Bootsnap
|
|
10
10
|
def initialize(store, path_obj, development_mode: false)
|
11
11
|
@development_mode = development_mode
|
12
12
|
@store = store
|
13
|
-
@mutex =
|
14
|
-
@path_obj = path_obj.map! { |f| File.exist?(f) ? File.realpath(f) : f }
|
13
|
+
@mutex = Mutex.new
|
14
|
+
@path_obj = path_obj.map! { |f| PathScanner.os_path(File.exist?(f) ? File.realpath(f) : f.dup) }
|
15
15
|
@has_relative_paths = nil
|
16
16
|
reinitialize
|
17
17
|
end
|
@@ -178,25 +178,42 @@ module Bootsnap
|
|
178
178
|
|
179
179
|
if DLEXT2
|
180
180
|
def search_index(f)
|
181
|
-
try_index(
|
181
|
+
try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f + DLEXT2) || try_index(f)
|
182
182
|
end
|
183
183
|
|
184
184
|
def maybe_append_extension(f)
|
185
|
-
try_ext(
|
185
|
+
try_ext(f + DOT_RB) || try_ext(f + DLEXT) || try_ext(f + DLEXT2) || f
|
186
186
|
end
|
187
187
|
else
|
188
188
|
def search_index(f)
|
189
|
-
try_index(
|
189
|
+
try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f)
|
190
190
|
end
|
191
191
|
|
192
192
|
def maybe_append_extension(f)
|
193
|
-
try_ext(
|
193
|
+
try_ext(f + DOT_RB) || try_ext(f + DLEXT) || f
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
-
|
198
|
-
|
199
|
-
|
197
|
+
s = rand.to_s.force_encoding(Encoding::US_ASCII).freeze
|
198
|
+
if s.respond_to?(:-@)
|
199
|
+
if (-s).equal?(s) && (-s.dup).equal?(s)
|
200
|
+
def try_index(f)
|
201
|
+
if (p = @index[f])
|
202
|
+
-(File.join(p, f).freeze)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
else
|
206
|
+
def try_index(f)
|
207
|
+
if (p = @index[f])
|
208
|
+
-File.join(p, f).untaint
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
else
|
213
|
+
def try_index(f)
|
214
|
+
if (p = @index[f])
|
215
|
+
File.join(p, f)
|
216
|
+
end
|
200
217
|
end
|
201
218
|
end
|
202
219
|
|
@@ -26,7 +26,7 @@ module Bootsnap
|
|
26
26
|
class LoadedFeaturesIndex
|
27
27
|
def initialize
|
28
28
|
@lfi = {}
|
29
|
-
@mutex =
|
29
|
+
@mutex = Mutex.new
|
30
30
|
|
31
31
|
# In theory the user could mutate $LOADED_FEATURES and invalidate our
|
32
32
|
# cache. If this ever comes up in practice — or if you, the
|
@@ -33,10 +33,10 @@ module Bootsnap
|
|
33
33
|
requirables = []
|
34
34
|
walk(path, nil) do |relative_path, absolute_path, is_directory|
|
35
35
|
if is_directory
|
36
|
-
dirs << relative_path
|
36
|
+
dirs << os_path(relative_path)
|
37
37
|
!contains_bundle_path || !absolute_path.start_with?(BUNDLE_PATH)
|
38
38
|
elsif relative_path.end_with?(*REQUIRABLE_EXTENSIONS)
|
39
|
-
requirables << relative_path
|
39
|
+
requirables << os_path(relative_path)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
[requirables, dirs]
|
@@ -45,7 +45,7 @@ module Bootsnap
|
|
45
45
|
def walk(absolute_dir_path, relative_dir_path, &block)
|
46
46
|
Dir.foreach(absolute_dir_path) do |name|
|
47
47
|
next if name.start_with?('.')
|
48
|
-
relative_path = relative_dir_path ?
|
48
|
+
relative_path = relative_dir_path ? File.join(relative_dir_path, name) : name
|
49
49
|
|
50
50
|
absolute_path = "#{absolute_dir_path}/#{name}"
|
51
51
|
if File.directory?(absolute_path)
|
@@ -57,6 +57,17 @@ module Bootsnap
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
if RUBY_VERSION >= '3.1'
|
62
|
+
def os_path(path)
|
63
|
+
path.freeze
|
64
|
+
end
|
65
|
+
else
|
66
|
+
def os_path(path)
|
67
|
+
path.force_encoding(Encoding::US_ASCII) if path.ascii_only?
|
68
|
+
path.freeze
|
69
|
+
end
|
70
|
+
end
|
60
71
|
end
|
61
72
|
end
|
62
73
|
end
|
@@ -12,8 +12,7 @@ module Bootsnap
|
|
12
12
|
|
13
13
|
def initialize(store_path)
|
14
14
|
@store_path = store_path
|
15
|
-
|
16
|
-
@txn_mutex = defined?(::Mutex) ? ::Mutex.new : ::Thread::Mutex.new
|
15
|
+
@txn_mutex = Mutex.new
|
17
16
|
@dirty = false
|
18
17
|
load_data
|
19
18
|
end
|
@@ -63,12 +62,18 @@ module Bootsnap
|
|
63
62
|
|
64
63
|
def load_data
|
65
64
|
@data = begin
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
65
|
+
File.open(@store_path, encoding: Encoding::BINARY) do |io|
|
66
|
+
MessagePack.load(io)
|
67
|
+
end
|
68
|
+
# handle malformed data due to upgrade incompatibility
|
69
|
+
rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
|
70
|
+
{}
|
71
|
+
rescue ArgumentError => error
|
72
|
+
if error.message =~ /negative array size/
|
73
|
+
{}
|
74
|
+
else
|
75
|
+
raise
|
76
|
+
end
|
72
77
|
end
|
73
78
|
end
|
74
79
|
|
@@ -80,7 +85,9 @@ module Bootsnap
|
|
80
85
|
exclusive_write = File::Constants::CREAT | File::Constants::EXCL | File::Constants::WRONLY
|
81
86
|
# `encoding:` looks redundant wrt `binwrite`, but necessary on windows
|
82
87
|
# because binary is part of mode.
|
83
|
-
File.
|
88
|
+
File.open(tmp, mode: exclusive_write, encoding: Encoding::BINARY) do |io|
|
89
|
+
MessagePack.dump(@data, io, freeze: true)
|
90
|
+
end
|
84
91
|
FileUtils.mv(tmp, @store_path)
|
85
92
|
rescue Errno::EEXIST
|
86
93
|
retry
|
data/lib/bootsnap/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bootsnap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Burke Libbey
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|