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 +4 -4
- data/CHANGELOG.md +7 -0
- data/ext/bootsnap/bootsnap.c +56 -19
- data/lib/bootsnap/compile_cache/iseq.rb +2 -2
- data/lib/bootsnap/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6227028d2a559d0e5129ef91915f65a064082b2e1326517dd67da2f11d91d194
|
|
4
|
+
data.tar.gz: 1c7cbf82581f9162601a7723812201d240661c0d3477373b820cf7e942b9d416
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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`.
|
data/ext/bootsnap/bootsnap.c
CHANGED
|
@@ -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 =
|
|
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
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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
|
|
data/lib/bootsnap/version.rb
CHANGED