bootsnap 1.4.4-java → 1.4.9-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +1 -1
- data/ext/bootsnap/bootsnap.c +113 -65
- data/ext/bootsnap/extconf.rb +1 -0
- data/lib/bootsnap.rb +2 -0
- data/lib/bootsnap/bundler.rb +1 -0
- data/lib/bootsnap/compile_cache.rb +4 -3
- data/lib/bootsnap/compile_cache/iseq.rb +6 -4
- data/lib/bootsnap/compile_cache/yaml.rb +67 -38
- data/lib/bootsnap/explicit_require.rb +1 -0
- data/lib/bootsnap/load_path_cache.rb +1 -1
- data/lib/bootsnap/load_path_cache/cache.rb +8 -8
- data/lib/bootsnap/load_path_cache/change_observer.rb +2 -1
- data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +1 -0
- data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +18 -5
- data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +1 -0
- data/lib/bootsnap/load_path_cache/loaded_features_index.rb +33 -10
- data/lib/bootsnap/load_path_cache/path.rb +3 -2
- data/lib/bootsnap/load_path_cache/path_scanner.rb +39 -26
- data/lib/bootsnap/load_path_cache/realpath_cache.rb +5 -5
- data/lib/bootsnap/load_path_cache/store.rb +18 -14
- data/lib/bootsnap/setup.rb +1 -0
- data/lib/bootsnap/version.rb +2 -1
- metadata +9 -26
- data/.github/CODEOWNERS +0 -2
- data/.github/probots.yml +0 -2
- data/.gitignore +0 -17
- data/.rubocop.yml +0 -20
- data/.travis.yml +0 -21
- data/CODE_OF_CONDUCT.md +0 -74
- data/CONTRIBUTING.md +0 -21
- data/Gemfile +0 -8
- data/README.jp.md +0 -231
- data/Rakefile +0 -12
- data/bin/ci +0 -10
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/bin/test-minimal-support +0 -7
- data/bin/testunit +0 -8
- data/bootsnap.gemspec +0 -45
- data/dev.yml +0 -10
- data/shipit.rubygems.yml +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4725339bc7effc3e8e78f210bb0a06302d2b2d53838def89cd329754efd38948
|
4
|
+
data.tar.gz: fe28e483feaaddcec205a692127e2537e34b655a949a287cf80ee46e1c53dddf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 229316c6ce5fc9494f17bc2907b2fae6782452f9379d10a18666cb02479ac387dc818bc40f861c07ae83eb4423a8f02a0e0d841e53af78b7d326f1274e805973
|
7
|
+
data.tar.gz: f45154c1ed2efbb613a2945a13d2b5428971c34fc098cad3e6b21291846f27fc09d853f0e3b66decb3782fb4a325e48136aa96a0135fcf98840a977a14503cd8
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
# 1.4.9
|
2
|
+
|
3
|
+
* [Windows support](https://github.com/Shopify/bootsnap/pull/319)
|
4
|
+
* [Fix potential crash](https://github.com/Shopify/bootsnap/pull/322)
|
5
|
+
|
6
|
+
# 1.4.8
|
7
|
+
|
8
|
+
* [Prevent FallbackScan from polluting exception cause](https://github.com/Shopify/bootsnap/pull/314)
|
9
|
+
|
10
|
+
# 1.4.7
|
11
|
+
|
12
|
+
* Various performance enhancements
|
13
|
+
* Fix race condition in heavy concurrent load scenarios that would cause bootsnap to raise
|
14
|
+
|
15
|
+
# 1.4.6
|
16
|
+
|
17
|
+
* Fix bug that was erroneously considering that files containing `.` in the names were being
|
18
|
+
required if a different file with the same name was already being required
|
19
|
+
|
20
|
+
Example:
|
21
|
+
|
22
|
+
require 'foo'
|
23
|
+
require 'foo.en'
|
24
|
+
|
25
|
+
Before bootsnap was considering `foo.en` to be the same file as `foo`
|
26
|
+
|
27
|
+
* Use glibc as part of the ruby_platform cache key
|
28
|
+
|
29
|
+
# 1.4.5
|
30
|
+
|
31
|
+
* MRI 2.7 support
|
32
|
+
* Fixed concurrency bugs
|
33
|
+
|
1
34
|
# 1.4.4
|
2
35
|
|
3
36
|
* Disable ISeq cache in `bootsnap/setup` by default in Ruby 2.5
|
data/README.md
CHANGED
@@ -214,7 +214,7 @@ Bootsnap writes a cache file containing a 64 byte header followed by the cache c
|
|
214
214
|
is a cache key including several fields:
|
215
215
|
|
216
216
|
* `version`, hardcoded in bootsnap. Essentially a schema version;
|
217
|
-
* `
|
217
|
+
* `ruby_platform`, A hash of `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) variable and glibc version (on Linux) or OS version (`uname -v` on BSD, macOS)
|
218
218
|
* `compile_option`, which changes with `RubyVM::InstructionSequence.compile_option` does;
|
219
219
|
* `ruby_revision`, the version of Ruby this was compiled with;
|
220
220
|
* `size`, the size of the source file;
|
data/ext/bootsnap/bootsnap.c
CHANGED
@@ -21,6 +21,9 @@
|
|
21
21
|
#ifndef _WIN32
|
22
22
|
#include <sys/utsname.h>
|
23
23
|
#endif
|
24
|
+
#ifdef __GLIBC__
|
25
|
+
#include <gnu/libc-version.h>
|
26
|
+
#endif
|
24
27
|
|
25
28
|
/* 1000 is an arbitrary limit; FNV64 plus some slashes brings the cap down to
|
26
29
|
* 981 for the cache dir */
|
@@ -29,6 +32,8 @@
|
|
29
32
|
|
30
33
|
#define KEY_SIZE 64
|
31
34
|
|
35
|
+
#define MAX_CREATE_TEMPFILE_ATTEMPT 3
|
36
|
+
|
32
37
|
/*
|
33
38
|
* An instance of this key is written as the first 64 bytes of each cache file.
|
34
39
|
* The mtime and size members track whether the file contents have changed, and
|
@@ -86,28 +91,29 @@ static ID uncompilable;
|
|
86
91
|
|
87
92
|
/* Functions exposed as module functions on Bootsnap::CompileCache::Native */
|
88
93
|
static VALUE bs_compile_option_crc32_set(VALUE self, VALUE crc32_v);
|
89
|
-
static VALUE bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler);
|
94
|
+
static VALUE bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler, VALUE args);
|
90
95
|
|
91
96
|
/* Helpers */
|
92
97
|
static uint64_t fnv1a_64(const char *str);
|
93
|
-
static void bs_cache_path(const char * cachedir, const char * path, char
|
98
|
+
static void bs_cache_path(const char * cachedir, const char * path, const char * extra, char (* cache_path)[MAX_CACHEPATH_SIZE]);
|
94
99
|
static int bs_read_key(int fd, struct bs_cache_key * key);
|
95
100
|
static int cache_key_equal(struct bs_cache_key * k1, struct bs_cache_key * k2);
|
96
|
-
static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler);
|
97
|
-
static int open_current_file(char * path, struct bs_cache_key * key, char ** errno_provenance);
|
98
|
-
static int fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data, int * exception_tag, char ** errno_provenance);
|
101
|
+
static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args);
|
102
|
+
static int open_current_file(char * path, struct bs_cache_key * key, const char ** errno_provenance);
|
103
|
+
static int fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE * output_data, int * exception_tag, const char ** errno_provenance);
|
104
|
+
static uint32_t get_ruby_revision(void);
|
99
105
|
static uint32_t get_ruby_platform(void);
|
100
106
|
|
101
107
|
/*
|
102
108
|
* Helper functions to call ruby methods on handler object without crashing on
|
103
109
|
* exception.
|
104
110
|
*/
|
105
|
-
static int bs_storage_to_output(VALUE handler, VALUE storage_data, VALUE * output_data);
|
111
|
+
static int bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * output_data);
|
106
112
|
static VALUE prot_storage_to_output(VALUE arg);
|
107
113
|
static VALUE prot_input_to_output(VALUE arg);
|
108
|
-
static void bs_input_to_output(VALUE handler, VALUE input_data, VALUE * output_data, int * exception_tag);
|
114
|
+
static void bs_input_to_output(VALUE handler, VALUE args, VALUE input_data, VALUE * output_data, int * exception_tag);
|
109
115
|
static VALUE prot_input_to_storage(VALUE arg);
|
110
|
-
static int bs_input_to_storage(VALUE handler, VALUE input_data, VALUE pathval, VALUE * storage_data);
|
116
|
+
static int bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data);
|
111
117
|
struct s2o_data;
|
112
118
|
struct i2o_data;
|
113
119
|
struct i2s_data;
|
@@ -136,13 +142,13 @@ Init_bootsnap(void)
|
|
136
142
|
rb_mBootsnap_CompileCache_Native = rb_define_module_under(rb_mBootsnap_CompileCache, "Native");
|
137
143
|
rb_eBootsnap_CompileCache_Uncompilable = rb_define_class_under(rb_mBootsnap_CompileCache, "Uncompilable", rb_eStandardError);
|
138
144
|
|
139
|
-
current_ruby_revision =
|
145
|
+
current_ruby_revision = get_ruby_revision();
|
140
146
|
current_ruby_platform = get_ruby_platform();
|
141
147
|
|
142
148
|
uncompilable = rb_intern("__bootsnap_uncompilable__");
|
143
149
|
|
144
150
|
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "coverage_running?", bs_rb_coverage_running, 0);
|
145
|
-
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "fetch", bs_rb_fetch,
|
151
|
+
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "fetch", bs_rb_fetch, 4);
|
146
152
|
rb_define_module_function(rb_mBootsnap_CompileCache_Native, "compile_option_crc32=", bs_compile_option_crc32_set, 1);
|
147
153
|
|
148
154
|
current_umask = umask(0777);
|
@@ -196,6 +202,26 @@ fnv1a_64(const char *str)
|
|
196
202
|
return fnv1a_64_iter(h, str);
|
197
203
|
}
|
198
204
|
|
205
|
+
/*
|
206
|
+
* Ruby's revision may be Integer or String. CRuby 2.7 or later uses
|
207
|
+
* Git commit ID as revision. It's String.
|
208
|
+
*/
|
209
|
+
static uint32_t
|
210
|
+
get_ruby_revision(void)
|
211
|
+
{
|
212
|
+
VALUE ruby_revision;
|
213
|
+
|
214
|
+
ruby_revision = rb_const_get(rb_cObject, rb_intern("RUBY_REVISION"));
|
215
|
+
if (RB_TYPE_P(ruby_revision, RUBY_T_FIXNUM)) {
|
216
|
+
return FIX2INT(ruby_revision);
|
217
|
+
} else {
|
218
|
+
uint64_t hash;
|
219
|
+
|
220
|
+
hash = fnv1a_64(StringValueCStr(ruby_revision));
|
221
|
+
return (uint32_t)(hash >> 32);
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
199
225
|
/*
|
200
226
|
* When ruby's version doesn't change, but it's recompiled on a different OS
|
201
227
|
* (or OS version), we need to invalidate the cache.
|
@@ -215,6 +241,9 @@ get_ruby_platform(void)
|
|
215
241
|
|
216
242
|
#ifdef _WIN32
|
217
243
|
return (uint32_t)(hash >> 32) ^ (uint32_t)GetVersion();
|
244
|
+
#elif defined(__GLIBC__)
|
245
|
+
hash = fnv1a_64_iter(hash, gnu_get_libc_version());
|
246
|
+
return (uint32_t)(hash >> 32);
|
218
247
|
#else
|
219
248
|
struct utsname utsname;
|
220
249
|
|
@@ -235,9 +264,12 @@ get_ruby_platform(void)
|
|
235
264
|
* The path will look something like: <cachedir>/12/34567890abcdef
|
236
265
|
*/
|
237
266
|
static void
|
238
|
-
bs_cache_path(const char * cachedir, const char * path, char
|
267
|
+
bs_cache_path(const char * cachedir, const char * path, const char * extra, char (* cache_path)[MAX_CACHEPATH_SIZE])
|
239
268
|
{
|
240
269
|
uint64_t hash = fnv1a_64(path);
|
270
|
+
if (extra) {
|
271
|
+
hash ^= fnv1a_64(extra);
|
272
|
+
}
|
241
273
|
|
242
274
|
uint8_t first_byte = (hash >> (64 - 8));
|
243
275
|
uint64_t remainder = hash & 0x00ffffffffffffff;
|
@@ -272,7 +304,7 @@ cache_key_equal(struct bs_cache_key * k1, struct bs_cache_key * k2)
|
|
272
304
|
* conversions on the ruby VALUE arguments before passing them along.
|
273
305
|
*/
|
274
306
|
static VALUE
|
275
|
-
bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
|
307
|
+
bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler, VALUE args)
|
276
308
|
{
|
277
309
|
FilePathValue(path_v);
|
278
310
|
|
@@ -286,13 +318,16 @@ bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
|
|
286
318
|
char * cachedir = RSTRING_PTR(cachedir_v);
|
287
319
|
char * path = RSTRING_PTR(path_v);
|
288
320
|
char cache_path[MAX_CACHEPATH_SIZE];
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
321
|
+
char * extra = NULL;
|
322
|
+
if (!NIL_P(args)) {
|
323
|
+
VALUE args_serial = rb_marshal_dump(args, Qnil);
|
324
|
+
extra = RSTRING_PTR(args_serial);
|
293
325
|
}
|
294
326
|
|
295
|
-
|
327
|
+
/* generate cache path to cache_path */
|
328
|
+
bs_cache_path(cachedir, path, extra, &cache_path);
|
329
|
+
|
330
|
+
return bs_fetch(path, path_v, cache_path, handler, args);
|
296
331
|
}
|
297
332
|
|
298
333
|
/*
|
@@ -300,14 +335,14 @@ bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
|
|
300
335
|
* was loaded.
|
301
336
|
*/
|
302
337
|
static int
|
303
|
-
open_current_file(char * path, struct bs_cache_key * key, char ** errno_provenance)
|
338
|
+
open_current_file(char * path, struct bs_cache_key * key, const char ** errno_provenance)
|
304
339
|
{
|
305
340
|
struct stat statbuf;
|
306
341
|
int fd;
|
307
342
|
|
308
343
|
fd = open(path, O_RDONLY);
|
309
344
|
if (fd < 0) {
|
310
|
-
*errno_provenance =
|
345
|
+
*errno_provenance = "bs_fetch:open_current_file:open";
|
311
346
|
return fd;
|
312
347
|
}
|
313
348
|
#ifdef _WIN32
|
@@ -315,7 +350,7 @@ open_current_file(char * path, struct bs_cache_key * key, char ** errno_provenan
|
|
315
350
|
#endif
|
316
351
|
|
317
352
|
if (fstat(fd, &statbuf) < 0) {
|
318
|
-
*errno_provenance =
|
353
|
+
*errno_provenance = "bs_fetch:open_current_file:fstat";
|
319
354
|
close(fd);
|
320
355
|
return -1;
|
321
356
|
}
|
@@ -361,13 +396,13 @@ bs_read_key(int fd, struct bs_cache_key * key)
|
|
361
396
|
* - ERROR_WITH_ERRNO (-1, errno is set)
|
362
397
|
*/
|
363
398
|
static int
|
364
|
-
open_cache_file(const char * path, struct bs_cache_key * key, char ** errno_provenance)
|
399
|
+
open_cache_file(const char * path, struct bs_cache_key * key, const char ** errno_provenance)
|
365
400
|
{
|
366
401
|
int fd, res;
|
367
402
|
|
368
403
|
fd = open(path, O_RDONLY);
|
369
404
|
if (fd < 0) {
|
370
|
-
*errno_provenance =
|
405
|
+
*errno_provenance = "bs_fetch:open_cache_file:open";
|
371
406
|
if (errno == ENOENT) return CACHE_MISSING_OR_INVALID;
|
372
407
|
return ERROR_WITH_ERRNO;
|
373
408
|
}
|
@@ -377,7 +412,7 @@ open_cache_file(const char * path, struct bs_cache_key * key, char ** errno_prov
|
|
377
412
|
|
378
413
|
res = bs_read_key(fd, key);
|
379
414
|
if (res < 0) {
|
380
|
-
*errno_provenance =
|
415
|
+
*errno_provenance = "bs_fetch:open_cache_file:read";
|
381
416
|
close(fd);
|
382
417
|
return res;
|
383
418
|
}
|
@@ -401,7 +436,7 @@ open_cache_file(const char * path, struct bs_cache_key * key, char ** errno_prov
|
|
401
436
|
* or exception, will be the final data returnable to the user.
|
402
437
|
*/
|
403
438
|
static int
|
404
|
-
fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data, int * exception_tag, char ** errno_provenance)
|
439
|
+
fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE * output_data, int * exception_tag, const char ** errno_provenance)
|
405
440
|
{
|
406
441
|
char * data = NULL;
|
407
442
|
ssize_t nread;
|
@@ -410,7 +445,7 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data,
|
|
410
445
|
VALUE storage_data;
|
411
446
|
|
412
447
|
if (data_size > 100000000000) {
|
413
|
-
*errno_provenance =
|
448
|
+
*errno_provenance = "bs_fetch:fetch_cached_data:datasize";
|
414
449
|
errno = EINVAL; /* because wtf? */
|
415
450
|
ret = -1;
|
416
451
|
goto done;
|
@@ -418,7 +453,7 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data,
|
|
418
453
|
data = ALLOC_N(char, data_size);
|
419
454
|
nread = read(fd, data, data_size);
|
420
455
|
if (nread < 0) {
|
421
|
-
*errno_provenance =
|
456
|
+
*errno_provenance = "bs_fetch:fetch_cached_data:read";
|
422
457
|
ret = -1;
|
423
458
|
goto done;
|
424
459
|
}
|
@@ -427,9 +462,9 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE * output_data,
|
|
427
462
|
goto done;
|
428
463
|
}
|
429
464
|
|
430
|
-
storage_data =
|
465
|
+
storage_data = rb_str_new(data, data_size);
|
431
466
|
|
432
|
-
*exception_tag = bs_storage_to_output(handler, storage_data, output_data);
|
467
|
+
*exception_tag = bs_storage_to_output(handler, args, storage_data, output_data);
|
433
468
|
ret = 0;
|
434
469
|
done:
|
435
470
|
if (data != NULL) xfree(data);
|
@@ -470,29 +505,36 @@ mkpath(char * file_path, mode_t mode)
|
|
470
505
|
* path.
|
471
506
|
*/
|
472
507
|
static int
|
473
|
-
atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, char ** errno_provenance)
|
508
|
+
atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, const char ** errno_provenance)
|
474
509
|
{
|
475
510
|
char template[MAX_CACHEPATH_SIZE + 20];
|
476
511
|
char * tmp_path;
|
477
|
-
int fd, ret;
|
512
|
+
int fd, ret, attempt;
|
478
513
|
ssize_t nwrite;
|
479
514
|
|
480
|
-
|
481
|
-
|
515
|
+
for (attempt = 0; attempt < MAX_CREATE_TEMPFILE_ATTEMPT; ++attempt) {
|
516
|
+
tmp_path = strncpy(template, path, MAX_CACHEPATH_SIZE);
|
517
|
+
strcat(tmp_path, ".tmp.XXXXXX");
|
482
518
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
}
|
490
|
-
fd = open(tmp_path, O_WRONLY | O_CREAT, 0664);
|
491
|
-
if (fd < 0) {
|
492
|
-
*errno_provenance = (char *)"bs_fetch:atomic_write_cache_file:open";
|
519
|
+
// mkstemp modifies the template to be the actual created path
|
520
|
+
fd = mkstemp(tmp_path);
|
521
|
+
if (fd > 0) break;
|
522
|
+
|
523
|
+
if (attempt == 0 && mkpath(tmp_path, 0775) < 0) {
|
524
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:mkpath";
|
493
525
|
return -1;
|
494
526
|
}
|
495
527
|
}
|
528
|
+
if (fd < 0) {
|
529
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:mkstemp";
|
530
|
+
return -1;
|
531
|
+
}
|
532
|
+
|
533
|
+
if (chmod(tmp_path, 0644) < 0) {
|
534
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:chmod";
|
535
|
+
return -1;
|
536
|
+
}
|
537
|
+
|
496
538
|
#ifdef _WIN32
|
497
539
|
setmode(fd, O_BINARY);
|
498
540
|
#endif
|
@@ -500,11 +542,11 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, char
|
|
500
542
|
key->data_size = RSTRING_LEN(data);
|
501
543
|
nwrite = write(fd, key, KEY_SIZE);
|
502
544
|
if (nwrite < 0) {
|
503
|
-
*errno_provenance =
|
545
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:write";
|
504
546
|
return -1;
|
505
547
|
}
|
506
548
|
if (nwrite != KEY_SIZE) {
|
507
|
-
*errno_provenance =
|
549
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:keysize";
|
508
550
|
errno = EIO; /* Lies but whatever */
|
509
551
|
return -1;
|
510
552
|
}
|
@@ -512,7 +554,7 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, char
|
|
512
554
|
nwrite = write(fd, RSTRING_PTR(data), RSTRING_LEN(data));
|
513
555
|
if (nwrite < 0) return -1;
|
514
556
|
if (nwrite != RSTRING_LEN(data)) {
|
515
|
-
*errno_provenance =
|
557
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:writelength";
|
516
558
|
errno = EIO; /* Lies but whatever */
|
517
559
|
return -1;
|
518
560
|
}
|
@@ -520,12 +562,12 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, char
|
|
520
562
|
close(fd);
|
521
563
|
ret = rename(tmp_path, path);
|
522
564
|
if (ret < 0) {
|
523
|
-
*errno_provenance =
|
565
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:rename";
|
524
566
|
return -1;
|
525
567
|
}
|
526
568
|
ret = chmod(path, 0664 & ~current_umask);
|
527
569
|
if (ret < 0) {
|
528
|
-
*errno_provenance =
|
570
|
+
*errno_provenance = "bs_fetch:atomic_write_cache_file:chmod";
|
529
571
|
}
|
530
572
|
return ret;
|
531
573
|
}
|
@@ -534,13 +576,13 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, char
|
|
534
576
|
/* Read contents from an fd, whose contents are asserted to be +size+ bytes
|
535
577
|
* long, into a buffer */
|
536
578
|
static ssize_t
|
537
|
-
bs_read_contents(int fd, size_t size, char ** contents, char ** errno_provenance)
|
579
|
+
bs_read_contents(int fd, size_t size, char ** contents, const char ** errno_provenance)
|
538
580
|
{
|
539
581
|
ssize_t nread;
|
540
582
|
*contents = ALLOC_N(char, size);
|
541
583
|
nread = read(fd, *contents, size);
|
542
584
|
if (nread < 0) {
|
543
|
-
*errno_provenance =
|
585
|
+
*errno_provenance = "bs_fetch:bs_read_contents:read";
|
544
586
|
}
|
545
587
|
return nread;
|
546
588
|
}
|
@@ -590,13 +632,13 @@ bs_read_contents(int fd, size_t size, char ** contents, char ** errno_provenance
|
|
590
632
|
* - Return storage_to_output(storage_data)
|
591
633
|
*/
|
592
634
|
static VALUE
|
593
|
-
bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
635
|
+
bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args)
|
594
636
|
{
|
595
637
|
struct bs_cache_key cached_key, current_key;
|
596
638
|
char * contents = NULL;
|
597
639
|
int cache_fd = -1, current_fd = -1;
|
598
640
|
int res, valid_cache = 0, exception_tag = 0;
|
599
|
-
char * errno_provenance = NULL;
|
641
|
+
const char * errno_provenance = NULL;
|
600
642
|
|
601
643
|
VALUE input_data; /* data read from source file, e.g. YAML or ruby source */
|
602
644
|
VALUE storage_data; /* compiled data, e.g. msgpack / binary iseq */
|
@@ -623,7 +665,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
623
665
|
if (valid_cache) {
|
624
666
|
/* Fetch the cache data and return it if we're able to load it successfully */
|
625
667
|
res = fetch_cached_data(
|
626
|
-
cache_fd, (ssize_t)cached_key.data_size, handler,
|
668
|
+
cache_fd, (ssize_t)cached_key.data_size, handler, args,
|
627
669
|
&output_data, &exception_tag, &errno_provenance
|
628
670
|
);
|
629
671
|
if (exception_tag != 0) goto raise;
|
@@ -637,15 +679,15 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
637
679
|
|
638
680
|
/* Read the contents of the source file into a buffer */
|
639
681
|
if (bs_read_contents(current_fd, current_key.size, &contents, &errno_provenance) < 0) goto fail_errno;
|
640
|
-
input_data =
|
682
|
+
input_data = rb_str_new(contents, current_key.size);
|
641
683
|
|
642
684
|
/* Try to compile the input_data using input_to_storage(input_data) */
|
643
|
-
exception_tag = bs_input_to_storage(handler, input_data, path_v, &storage_data);
|
685
|
+
exception_tag = bs_input_to_storage(handler, args, input_data, path_v, &storage_data);
|
644
686
|
if (exception_tag != 0) goto raise;
|
645
687
|
/* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
|
646
688
|
* to cache anything; just return input_to_output(input_data) */
|
647
689
|
if (storage_data == uncompilable) {
|
648
|
-
bs_input_to_output(handler, input_data, &output_data, &exception_tag);
|
690
|
+
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
649
691
|
if (exception_tag != 0) goto raise;
|
650
692
|
goto succeed;
|
651
693
|
}
|
@@ -657,17 +699,17 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
657
699
|
if (res < 0) goto fail_errno;
|
658
700
|
|
659
701
|
/* Having written the cache, now convert storage_data to output_data */
|
660
|
-
exception_tag = bs_storage_to_output(handler, storage_data, &output_data);
|
702
|
+
exception_tag = bs_storage_to_output(handler, args, storage_data, &output_data);
|
661
703
|
if (exception_tag != 0) goto raise;
|
662
704
|
|
663
705
|
/* If output_data is nil, delete the cache entry and generate the output
|
664
706
|
* using input_to_output */
|
665
707
|
if (NIL_P(output_data)) {
|
666
708
|
if (unlink(cache_path) < 0) {
|
667
|
-
errno_provenance =
|
709
|
+
errno_provenance = "bs_fetch:unlink";
|
668
710
|
goto fail_errno;
|
669
711
|
}
|
670
|
-
bs_input_to_output(handler, input_data, &output_data, &exception_tag);
|
712
|
+
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
671
713
|
if (exception_tag != 0) goto raise;
|
672
714
|
}
|
673
715
|
|
@@ -717,16 +759,19 @@ invalid_type_storage_data:
|
|
717
759
|
|
718
760
|
struct s2o_data {
|
719
761
|
VALUE handler;
|
762
|
+
VALUE args;
|
720
763
|
VALUE storage_data;
|
721
764
|
};
|
722
765
|
|
723
766
|
struct i2o_data {
|
724
767
|
VALUE handler;
|
768
|
+
VALUE args;
|
725
769
|
VALUE input_data;
|
726
770
|
};
|
727
771
|
|
728
772
|
struct i2s_data {
|
729
773
|
VALUE handler;
|
774
|
+
VALUE args;
|
730
775
|
VALUE input_data;
|
731
776
|
VALUE pathval;
|
732
777
|
};
|
@@ -735,15 +780,16 @@ static VALUE
|
|
735
780
|
prot_storage_to_output(VALUE arg)
|
736
781
|
{
|
737
782
|
struct s2o_data * data = (struct s2o_data *)arg;
|
738
|
-
return rb_funcall(data->handler, rb_intern("storage_to_output"),
|
783
|
+
return rb_funcall(data->handler, rb_intern("storage_to_output"), 2, data->storage_data, data->args);
|
739
784
|
}
|
740
785
|
|
741
786
|
static int
|
742
|
-
bs_storage_to_output(VALUE handler, VALUE storage_data, VALUE * output_data)
|
787
|
+
bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * output_data)
|
743
788
|
{
|
744
789
|
int state;
|
745
790
|
struct s2o_data s2o_data = {
|
746
791
|
.handler = handler,
|
792
|
+
.args = args,
|
747
793
|
.storage_data = storage_data,
|
748
794
|
};
|
749
795
|
*output_data = rb_protect(prot_storage_to_output, (VALUE)&s2o_data, &state);
|
@@ -751,10 +797,11 @@ bs_storage_to_output(VALUE handler, VALUE storage_data, VALUE * output_data)
|
|
751
797
|
}
|
752
798
|
|
753
799
|
static void
|
754
|
-
bs_input_to_output(VALUE handler, VALUE input_data, VALUE * output_data, int * exception_tag)
|
800
|
+
bs_input_to_output(VALUE handler, VALUE args, VALUE input_data, VALUE * output_data, int * exception_tag)
|
755
801
|
{
|
756
802
|
struct i2o_data i2o_data = {
|
757
803
|
.handler = handler,
|
804
|
+
.args = args,
|
758
805
|
.input_data = input_data,
|
759
806
|
};
|
760
807
|
*output_data = rb_protect(prot_input_to_output, (VALUE)&i2o_data, exception_tag);
|
@@ -764,18 +811,18 @@ static VALUE
|
|
764
811
|
prot_input_to_output(VALUE arg)
|
765
812
|
{
|
766
813
|
struct i2o_data * data = (struct i2o_data *)arg;
|
767
|
-
return rb_funcall(data->handler, rb_intern("input_to_output"),
|
814
|
+
return rb_funcall(data->handler, rb_intern("input_to_output"), 2, data->input_data, data->args);
|
768
815
|
}
|
769
816
|
|
770
817
|
static VALUE
|
771
818
|
try_input_to_storage(VALUE arg)
|
772
819
|
{
|
773
820
|
struct i2s_data * data = (struct i2s_data *)arg;
|
774
|
-
return rb_funcall(data->handler, rb_intern("input_to_storage"),
|
821
|
+
return rb_funcall(data->handler, rb_intern("input_to_storage"), 3, data->input_data, data->pathval, data->args);
|
775
822
|
}
|
776
823
|
|
777
824
|
static VALUE
|
778
|
-
rescue_input_to_storage(VALUE arg)
|
825
|
+
rescue_input_to_storage(VALUE arg, VALUE e)
|
779
826
|
{
|
780
827
|
return uncompilable;
|
781
828
|
}
|
@@ -791,11 +838,12 @@ prot_input_to_storage(VALUE arg)
|
|
791
838
|
}
|
792
839
|
|
793
840
|
static int
|
794
|
-
bs_input_to_storage(VALUE handler, VALUE input_data, VALUE pathval, VALUE * storage_data)
|
841
|
+
bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data)
|
795
842
|
{
|
796
843
|
int state;
|
797
844
|
struct i2s_data i2s_data = {
|
798
845
|
.handler = handler,
|
846
|
+
.args = args,
|
799
847
|
.input_data = input_data,
|
800
848
|
.pathval = pathval,
|
801
849
|
};
|