bootsnap 1.4.4-java → 1.4.9-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
};
|