bootsnap 1.18.0 → 1.18.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52fa7adde2726e79c8d06b4ca8a450d0ecc0fd143b377a0da3aa27965e5ecd52
4
- data.tar.gz: 7029e821fbd1da561f14fce91cc3ca72f8ee80eb6ead5a099bc37b74233c9dce
3
+ metadata.gz: 219e1686c3d7b3a3c3d0e4814c27842f1e1e9ab35958a1a655532ccaedfa4702
4
+ data.tar.gz: 439966933d2dea1cf428b6b61d5e8e72e3c9e7963a00938aff46622a5f7342bf
5
5
  SHA512:
6
- metadata.gz: bce0d723ae15e1fcc8961b698977977a49587d4fe514c76dd10d97453808c6562681e9df80dd3ecec2f1eff70f8a54592027c699d37c4c39e9254c6b63507f6b
7
- data.tar.gz: 8272f4541d3789e8eb390319ec04d202b90fc0745696f73d414a7dc1365380246ec7b44746b3592abf19883eae709f2daf4e5033677b7be3490dc0ad642fb6d7
6
+ metadata.gz: 6232067f5e67dc414233738b2d1e6390cf17726d78efe6150d30ccd7b7d2e206c68515ddb182988537331982e206be60e3c974fba779ca98a42810084507a827
7
+ data.tar.gz: 6d7aa8fc570210a4798903e6150a5e97de4d67e29729c8a04db3ca2aae7bd47f3d9257e8b961158155103306e4ec99f8d50a94cac2c2798c86471d7219038d49
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Unreleased
2
2
 
3
+ # 1.18.2
4
+
5
+ * Disable stale cache entries revalidation by default as it seems to cause cache corruption issues. See #471 and #474.
6
+ Will be re-enabled in a future version once the root cause is identified.
7
+ * Fix a potential compilation issue on some systems. See #470.
8
+
9
+ # 1.18.1
10
+
11
+ * Handle `EPERM` errors when opening files with `O_NOATIME`.
12
+
3
13
  # 1.18.0
4
14
 
5
15
  * `Bootsnap.instrumentation` now receive `:hit` events.
@@ -18,8 +18,15 @@
18
18
  #include <sys/types.h>
19
19
  #include <errno.h>
20
20
  #include <fcntl.h>
21
+ #include <unistd.h>
21
22
  #include <sys/stat.h>
22
23
 
24
+ #ifdef __APPLE__
25
+ // The symbol is present, however not in the headers
26
+ // See: https://github.com/Shopify/bootsnap/issues/470
27
+ extern int fdatasync(int);
28
+ #endif
29
+
23
30
  #ifndef O_NOATIME
24
31
  #define O_NOATIME 0
25
32
  #endif
@@ -96,10 +103,13 @@ static ID instrumentation_method;
96
103
  static VALUE sym_hit, sym_miss, sym_stale, sym_revalidated;
97
104
  static bool instrumentation_enabled = false;
98
105
  static bool readonly = false;
106
+ static bool revalidation = false;
107
+ static bool perm_issue = false;
99
108
 
100
109
  /* Functions exposed as module functions on Bootsnap::CompileCache::Native */
101
110
  static VALUE bs_instrumentation_enabled_set(VALUE self, VALUE enabled);
102
111
  static VALUE bs_readonly_set(VALUE self, VALUE enabled);
112
+ static VALUE bs_revalidation_set(VALUE self, VALUE enabled);
103
113
  static VALUE bs_compile_option_crc32_set(VALUE self, VALUE crc32_v);
104
114
  static VALUE bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler, VALUE args);
105
115
  static VALUE bs_rb_precompile(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler);
@@ -119,7 +129,7 @@ static int update_cache_key(struct bs_cache_key *current_key, int cache_fd, cons
119
129
  static void bs_cache_key_digest(struct bs_cache_key * key, const VALUE input_data);
120
130
  static VALUE bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args);
121
131
  static VALUE bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler);
122
- static int open_current_file(char * path, struct bs_cache_key * key, const char ** errno_provenance);
132
+ static int open_current_file(const char * path, struct bs_cache_key * key, const char ** errno_provenance);
123
133
  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);
124
134
  static uint32_t get_ruby_revision(void);
125
135
  static uint32_t get_ruby_platform(void);
@@ -182,6 +192,7 @@ Init_bootsnap(void)
182
192
 
183
193
  rb_define_module_function(rb_mBootsnap, "instrumentation_enabled=", bs_instrumentation_enabled_set, 1);
184
194
  rb_define_module_function(rb_mBootsnap_CompileCache_Native, "readonly=", bs_readonly_set, 1);
195
+ rb_define_module_function(rb_mBootsnap_CompileCache_Native, "revalidation=", bs_revalidation_set, 1);
185
196
  rb_define_module_function(rb_mBootsnap_CompileCache_Native, "coverage_running?", bs_rb_coverage_running, 0);
186
197
  rb_define_module_function(rb_mBootsnap_CompileCache_Native, "fetch", bs_rb_fetch, 4);
187
198
  rb_define_module_function(rb_mBootsnap_CompileCache_Native, "precompile", bs_rb_precompile, 3);
@@ -213,6 +224,13 @@ bs_readonly_set(VALUE self, VALUE enabled)
213
224
  return enabled;
214
225
  }
215
226
 
227
+ static VALUE
228
+ bs_revalidation_set(VALUE self, VALUE enabled)
229
+ {
230
+ revalidation = RTEST(enabled);
231
+ return enabled;
232
+ }
233
+
216
234
  /*
217
235
  * Bootsnap's ruby code registers a hook that notifies us via this function
218
236
  * when compile_option changes. These changes invalidate all existing caches.
@@ -317,7 +335,12 @@ static enum cache_status cache_key_equal_fast_path(struct bs_cache_key *k1,
317
335
  k1->ruby_platform == k2->ruby_platform &&
318
336
  k1->compile_option == k2->compile_option &&
319
337
  k1->ruby_revision == k2->ruby_revision && k1->size == k2->size) {
320
- return (k1->mtime == k2->mtime) ? hit : stale;
338
+ if (k1->mtime == k2->mtime) {
339
+ return hit;
340
+ }
341
+ if (revalidation) {
342
+ return stale;
343
+ }
321
344
  }
322
345
  return miss;
323
346
  }
@@ -413,17 +436,34 @@ bs_rb_precompile(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
413
436
 
414
437
  return bs_precompile(path, path_v, cache_path, handler);
415
438
  }
439
+
440
+ static int bs_open_noatime(const char *path, int flags) {
441
+ int fd = 1;
442
+ if (!perm_issue) {
443
+ fd = open(path, flags | O_NOATIME);
444
+ if (fd < 0 && errno == EPERM) {
445
+ errno = 0;
446
+ perm_issue = true;
447
+ }
448
+ }
449
+
450
+ if (perm_issue) {
451
+ fd = open(path, flags);
452
+ }
453
+ return fd;
454
+ }
455
+
416
456
  /*
417
457
  * Open the file we want to load/cache and generate a cache key for it if it
418
458
  * was loaded.
419
459
  */
420
460
  static int
421
- open_current_file(char * path, struct bs_cache_key * key, const char ** errno_provenance)
461
+ open_current_file(const char * path, struct bs_cache_key * key, const char ** errno_provenance)
422
462
  {
423
463
  struct stat statbuf;
424
464
  int fd;
425
465
 
426
- fd = open(path, O_RDONLY | O_NOATIME);
466
+ fd = bs_open_noatime(path, O_RDONLY);
427
467
  if (fd < 0) {
428
468
  *errno_provenance = "bs_fetch:open_current_file:open";
429
469
  return fd;
@@ -490,10 +530,10 @@ open_cache_file(const char * path, struct bs_cache_key * key, const char ** errn
490
530
  {
491
531
  int fd, res;
492
532
 
493
- if (readonly) {
494
- fd = open(path, O_RDONLY | O_NOATIME);
533
+ if (readonly || !revalidation) {
534
+ fd = bs_open_noatime(path, O_RDONLY);
495
535
  } else {
496
- fd = open(path, O_RDWR | O_NOATIME);
536
+ fd = bs_open_noatime(path, O_RDWR);
497
537
  }
498
538
 
499
539
  if (fd < 0) {
@@ -890,6 +930,12 @@ succeed:
890
930
  return output_data;
891
931
  fail_errno:
892
932
  CLEANUP;
933
+ if (errno_provenance) {
934
+ exception_message = rb_str_concat(
935
+ rb_str_new_cstr(errno_provenance),
936
+ rb_str_concat(rb_str_new_cstr(": "), exception_message)
937
+ );
938
+ }
893
939
  exception = rb_syserr_new_str(errno, exception_message);
894
940
  rb_exc_raise(exception);
895
941
  __builtin_unreachable();
@@ -3,10 +3,10 @@
3
3
  require "mkmf"
4
4
 
5
5
  if %w[ruby truffleruby].include?(RUBY_ENGINE)
6
- have_func "fdatasync", "fcntl.h"
6
+ have_func "fdatasync", "unistd.h"
7
7
 
8
8
  unless RUBY_PLATFORM.match?(/mswin|mingw|cygwin/)
9
- append_cppflags ["_GNU_SOURCE"] # Needed of O_NOATIME
9
+ append_cppflags ["-D_GNU_SOURCE"] # Needed of O_NOATIME
10
10
  end
11
11
 
12
12
  append_cflags ["-O3", "-std=c99"]
@@ -9,7 +9,7 @@ module Bootsnap
9
9
 
10
10
  Error = Class.new(StandardError)
11
11
 
12
- def self.setup(cache_dir:, iseq:, yaml:, json:, readonly: false)
12
+ def self.setup(cache_dir:, iseq:, yaml:, json:, readonly: false, revalidation: false)
13
13
  if iseq
14
14
  if supported?
15
15
  require_relative "compile_cache/iseq"
@@ -39,6 +39,7 @@ module Bootsnap
39
39
 
40
40
  if supported? && defined?(Bootsnap::CompileCache::Native)
41
41
  Bootsnap::CompileCache::Native.readonly = readonly
42
+ Bootsnap::CompileCache::Native.revalidation = revalidation
42
43
  end
43
44
  end
44
45
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bootsnap
4
- VERSION = "1.18.0"
4
+ VERSION = "1.18.2"
5
5
  end
data/lib/bootsnap.rb CHANGED
@@ -51,6 +51,7 @@ module Bootsnap
51
51
  load_path_cache: true,
52
52
  ignore_directories: nil,
53
53
  readonly: false,
54
+ revalidation: false,
54
55
  compile_cache_iseq: true,
55
56
  compile_cache_yaml: true,
56
57
  compile_cache_json: true
@@ -70,6 +71,7 @@ module Bootsnap
70
71
  yaml: compile_cache_yaml,
71
72
  json: compile_cache_json,
72
73
  readonly: readonly,
74
+ revalidation: revalidation,
73
75
  )
74
76
  end
75
77
 
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.18.0
4
+ version: 1.18.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-30 00:00:00.000000000 Z
11
+ date: 2024-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack