bootsnap 1.25.0 → 1.26.0

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: e46c28f258eb76b8c90fa22a7fa2c83887695b7c12d3aff8dbbefda5051dca87
4
- data.tar.gz: 33aaa301627c53d2f4db1b8e98db0b2f52dc8d20aa533c8de8dc9448bf0c0b8e
3
+ metadata.gz: 6227028d2a559d0e5129ef91915f65a064082b2e1326517dd67da2f11d91d194
4
+ data.tar.gz: 1c7cbf82581f9162601a7723812201d240661c0d3477373b820cf7e942b9d416
5
5
  SHA512:
6
- metadata.gz: 77f885b700f2d249da6afd6ed4a70e4b37bf27303ddabefdfbed915fea6e61587d3e0fa56ee5159a95416072d58d4994498ee29bf69a3ab70c3b9e98471c3a0a
7
- data.tar.gz: 7044ce0c6a30d7312d947da11b20755dbd496ee7b5f460293bf9188c83493ac951e6e683f75009b17860c45a7ff31e3264abffd69dcaf5a0e8c6b759b7631332
6
+ metadata.gz: 385183b9de17b6f72634b7307fdfc5481108afc06554b48bb2dede97e51ba4275d076357934d338286fceb3a221f1468ec2ea10e2f0f869de5a7b5b97fc444a8
7
+ data.tar.gz: c74bb8bdfe0e6f3615bbc4a6ea4f7c5a7a1d8589a3469da964c25b44451fbb3f54f10521b8549dc6ac400d7fb17ba4a686b5b289115e8b3bac81d7a5449e3c0b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Unreleased
2
2
 
3
+ # 1.26.0
4
+
5
+ * Handle top level `Coverage` constant being defined, but without it being the true stdlib `coverage` module.
6
+ * Fix `bootsnap precompile` that could generate a corrupted cache entry if an already cached YAML file was modified
7
+ without changing its size.
8
+ * Workaround a potential Ruby SEGV if `Bootsnap.instrumentation` raised an error.
9
+
3
10
  # 1.25.0
4
11
 
5
12
  * Improve YAML parsing cache to more efficiently handle `Time`, `Date` and `DateTime`.
@@ -318,7 +318,13 @@ static inline void
318
318
  bs_instrumentation(VALUE event, VALUE path)
319
319
  {
320
320
  if (RB_UNLIKELY(instrumentation_enabled)) {
321
+ // If the funcall raises and rescues an error we will lose the errinfo
322
+ // that exists now so we save it before and restore it after.
323
+ VALUE saved_errinfo = rb_errinfo();
321
324
  rb_funcall(rb_mBootsnap, instrumentation_method, 2, event, path);
325
+ // If the ruby code in instrumentation_method raised we won't reach this point.
326
+ // If it didn't raise it _might_ have rescued so we should restore errinfo.
327
+ rb_set_errinfo(saved_errinfo);
322
328
  }
323
329
  }
324
330
 
@@ -456,11 +462,34 @@ static int cache_key_equal_slow_path(struct bs_cache_key *current_key,
456
462
  return current_key->digest == cached_key->digest;
457
463
  }
458
464
 
465
+ static ssize_t
466
+ resumable_write(int fd, const void *buf, size_t count)
467
+ {
468
+ size_t total_written = 0;
469
+ const char *ptr = buf;
470
+
471
+ while (count > 0) {
472
+ ssize_t res = write(fd, ptr, count);
473
+
474
+ if (res < 0) {
475
+ if (errno == EINTR) {
476
+ continue; // Interrupted by signal, try again
477
+ }
478
+ return -1; // Real error
479
+ }
480
+
481
+ ptr += res;
482
+ count -= res;
483
+ total_written += res;
484
+ }
485
+ return total_written;
486
+ }
487
+
459
488
  static int update_cache_key(struct bs_cache_key *current_key, struct bs_cache_key *old_key, int cache_fd, const char ** errno_provenance)
460
489
  {
461
490
  old_key->mtime = current_key->mtime;
462
491
  lseek(cache_fd, 0, SEEK_SET);
463
- ssize_t nwrite = write(cache_fd, old_key, KEY_SIZE);
492
+ ssize_t nwrite = resumable_write(cache_fd, old_key, KEY_SIZE);
464
493
  if (nwrite < 0) {
465
494
  *errno_provenance = "update_cache_key:write";
466
495
  return -1;
@@ -725,6 +754,17 @@ mkpath(char * file_path, mode_t mode)
725
754
  return 0;
726
755
  }
727
756
 
757
+ static int
758
+ bs_fchmod(int fd, const char *path, mode_t mode)
759
+ {
760
+ #ifdef _WIN32
761
+ setmode(fd, O_BINARY);
762
+ return chmod(path, mode);
763
+ #else
764
+ return fchmod(fd, mode);
765
+ #endif
766
+ }
767
+
728
768
  /*
729
769
  * Write a cache header/key and a compiled artifact to a given cache path by
730
770
  * writing to a tmpfile and then renaming the tmpfile over top of the final
@@ -738,13 +778,18 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, cons
738
778
  int fd, ret, attempt;
739
779
  ssize_t nwrite;
740
780
 
781
+ uint64_t data_size = RSTRING_LEN(data);
782
+ if (data_size > (uint32_t)-1) {
783
+ return 0; // Don't cache.
784
+ }
785
+
741
786
  for (attempt = 0; attempt < MAX_CREATE_TEMPFILE_ATTEMPT; ++attempt) {
742
787
  tmp_path = strncpy(template, path, MAX_CACHEPATH_SIZE);
743
788
  strcat(tmp_path, ".tmp.XXXXXX");
744
789
 
745
790
  // mkstemp modifies the template to be the actual created path
746
791
  fd = mkstemp(tmp_path);
747
- if (fd > 0) break;
792
+ if (fd >= 0) break;
748
793
 
749
794
  if (attempt == 0 && mkpath(tmp_path, 0775) < 0) {
750
795
  *errno_provenance = "bs_fetch:atomic_write_cache_file:mkpath";
@@ -756,50 +801,42 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, cons
756
801
  return -1;
757
802
  }
758
803
 
759
- if (chmod(tmp_path, 0644) < 0) {
804
+ if (bs_fchmod(fd, tmp_path, 0644 & ~current_umask) < 0) {
805
+ close(fd);
760
806
  *errno_provenance = "bs_fetch:atomic_write_cache_file:chmod";
761
807
  return -1;
762
808
  }
763
809
 
764
- #ifdef _WIN32
765
- setmode(fd, O_BINARY);
766
- #endif
767
-
768
- uint64_t data_size = RSTRING_LEN(data);
769
- if (data_size > (uint32_t)-1) {
770
- return 0; // Don't cache.
771
- }
772
-
773
810
  key->data_size = (uint32_t)data_size;
774
- nwrite = write(fd, key, KEY_SIZE);
811
+ nwrite = resumable_write(fd, key, KEY_SIZE);
775
812
  if (nwrite < 0) {
813
+ close(fd);
776
814
  *errno_provenance = "bs_fetch:atomic_write_cache_file:write";
777
815
  return -1;
778
816
  }
779
817
  if (nwrite != KEY_SIZE) {
818
+ close(fd);
780
819
  *errno_provenance = "bs_fetch:atomic_write_cache_file:keysize";
781
820
  errno = EIO; /* Lies but whatever */
782
821
  return -1;
783
822
  }
784
823
 
785
- nwrite = write(fd, RSTRING_PTR(data), RSTRING_LEN(data));
824
+ nwrite = resumable_write(fd, RSTRING_PTR(data), RSTRING_LEN(data));
786
825
  if (nwrite < 0) return -1;
787
826
  if (nwrite != RSTRING_LEN(data)) {
827
+ close(fd);
788
828
  *errno_provenance = "bs_fetch:atomic_write_cache_file:writelength";
789
829
  errno = EIO; /* Lies but whatever */
790
830
  return -1;
791
831
  }
792
832
 
793
833
  close(fd);
834
+
794
835
  ret = rename(tmp_path, path);
795
836
  if (ret < 0) {
796
837
  *errno_provenance = "bs_fetch:atomic_write_cache_file:rename";
797
838
  return -1;
798
839
  }
799
- ret = chmod(path, 0664 & ~current_umask);
800
- if (ret < 0) {
801
- *errno_provenance = "bs_fetch:atomic_write_cache_file:chmod";
802
- }
803
840
  return ret;
804
841
  }
805
842
 
@@ -1105,7 +1142,7 @@ bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler)
1105
1142
  /* Cache is stale, invalid, or missing. Regenerate and write it out. */
1106
1143
 
1107
1144
  /* Read the contents of the source file into a buffer */
1108
- if ((input_data = bs_read_contents(current_fd, current_key.size, &errno_provenance)) == Qfalse) goto fail;
1145
+ if (input_data == Qfalse && (input_data = bs_read_contents(current_fd, current_key.size, &errno_provenance)) == Qfalse) goto fail;
1109
1146
 
1110
1147
  /* Try to compile the input_data using input_to_storage(input_data) */
1111
1148
  exception_tag = bs_input_to_storage(handler, Qnil, input_data, path_v, &storage_data);
@@ -172,11 +172,11 @@ module Bootsnap
172
172
 
173
173
  if RUBY_VERSION < "3.1."
174
174
  def self.coverage_on?
175
- defined?(Coverage) && Coverage.running?
175
+ defined?(Coverage.running?) && Coverage.running?
176
176
  end
177
177
  else
178
178
  def self.coverage_on?
179
- defined?(Coverage) && Coverage.state != :idle
179
+ defined?(Coverage.state) && Coverage.state != :idle
180
180
  end
181
181
  end
182
182
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bootsnap
4
- VERSION = "1.25.0"
4
+ VERSION = "1.26.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.25.0
4
+ version: 1.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey