bootsnap 1.7.2 → 1.11.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea223ff0ae18f28970e2b80aa24970fe24f5eeefc7ad12b5b4b77dc921af4ca3
4
- data.tar.gz: 5f9ffdfcbeac27b128aa314749dd27c6182247fe7b6aa6492a1d99d00586ac3e
3
+ metadata.gz: 1cc142349008790c310bcbc875a437996403242e579f85fb48f46eceecb383ad
4
+ data.tar.gz: fa1d21fafa8a4fa4d44ced76d597b773d3321e077dc815ccbcae3fe9dc4e661a
5
5
  SHA512:
6
- metadata.gz: 0e3bcea4690954e6e15a3b0c10e3bf5b93b23fefff0d3d61354cb04d683bd8925d61ce32dcc9f7dd526b2f14f4d44a24196e72003fa75714bb0e6f99fbc94f62
7
- data.tar.gz: 587454d2a3a5019c56c81068e9202905328e7c2918f1786f35ff988424e2a9222b36db35f7ef6e403fc730a0752508ab248b06d6b164dc0b6e147623e5f0912e
6
+ metadata.gz: 81445538692ae0dc34b7309c44195fce5c864e508afe6eed4124d3d87bc1bfa07fd2ddb2c602faa2409f1537f8da63b885fd692bdc74e961febdd2a39e6e1919
7
+ data.tar.gz: 6389ce3a667c528660976665ce8184fb61d638da6cd4040e7b2d55441679574bdf691e4991294396c19a6e79bbf185ba1cdca848d5ea499a5b8e197dca143a5f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,129 @@
1
1
  # Unreleased
2
2
 
3
+ # 1.11.1
4
+
5
+ * Fix the `can't modify frozen Hash` error on load path cache mutation. See #411.
6
+
7
+ # 1.11.0
8
+
9
+ * Drop dependency on `fileutils`.
10
+
11
+ * Better respect `Kernel#require` duck typing. While it almost never comes up in practice, `Kernel#require`
12
+ follow a fairly intricate duck-typing protocol on its argument implemented as `rb_get_path(VALUE)` in MRI.
13
+ So when applicable we bind `rb_get_path` and use it for improved compatibility. See #396 and #406.
14
+
15
+ * Get rid of the `Kernel.require_relative` decorator by resolving `$LOAD_PATH` members to their real path.
16
+ This way we handle symlinks in `$LOAD_PATH` much more efficiently. See #402 for the detailed explanation.
17
+
18
+ * Drop support for Ruby 2.3 (to allow getting rid of the `Kernel.require_relative` decorator).
19
+
20
+ # 1.10.3
21
+
22
+ * Fix Regexp and Date type support in YAML compile cache. (#400)
23
+
24
+ * Improve the YAML compile cache to support `UTF-8` symbols. (#398, #399)
25
+ [The default `MessagePack` symbol serializer assumes all symbols are ASCII](https://github.com/msgpack/msgpack-ruby/pull/211),
26
+ because of this, non-ASCII compatible symbol would be restored with `ASCII_8BIT` encoding (AKA `BINARY`).
27
+ Bootsnap now properly cache them in `UTF-8`.
28
+
29
+ Note that the above only apply for actual YAML symbols (e..g `--- :foo`).
30
+ The issue is still present for string keys parsed with `YAML.load_file(..., symbolize_names: true)`, that is a bug
31
+ in `msgpack` that will hopefully be solved soon, see: https://github.com/msgpack/msgpack-ruby/pull/246
32
+
33
+ * Entirely disable the YAML compile cache if `Encoding.default_internal` is set to an encoding not supported by `msgpack`. (#398)
34
+ `Psych` coerce strings to `Encoding.default_internal`, but `MessagePack` doesn't. So in this scenario we can't provide
35
+ YAML caching at all without returning the strings in the wrong encoding.
36
+ This never came up in practice but might as well be safe.
37
+
38
+ # 1.10.2
39
+
40
+ * Reduce the `Kernel.require` extra stack frames some more. Now bootsnap should only add one extra frame per `require` call.
41
+
42
+ * Better check `freeze` option support in JSON compile cache.
43
+ Previously `JSON.load_file(..., freeze: true)` would be cached even when the msgpack version is missing support for it.
44
+
45
+ # 1.10.1
46
+
47
+ * Fix `Kernel#autoload`'s fallback path always being executed.
48
+
49
+ * Consider `unlink` failing with `ENOENT` as a success.
50
+
51
+ # 1.10.0
52
+
53
+ * Delay requiring `FileUtils`. (#285)
54
+ `FileUtils` can be installed as a gem, so it's best to wait for bundler to have setup the load path before requiring it.
55
+
56
+ * Improve support of Psych 4. (#392)
57
+ Since `1.8.0`, `YAML.load_file` was no longer cached when Psych 4 was used. This is because `load_file` loads
58
+ in safe mode by default, so the Bootsnap cache could defeat that safety.
59
+ Now when precompiling YAML files, Bootsnap first try to parse them in safe mode, and if it can't fallback to unsafe mode,
60
+ and the cache contains a flag that records whether it was generated in safe mode or not.
61
+ `YAML.unsafe_load_file` will use safe caches just fine, but `YAML.load_file` will fallback to uncached YAML parsing
62
+ if the cache was generated using unsafe parsing.
63
+
64
+ * Minimize the Kernel.require extra stack frames. (#393)
65
+ This should reduce the noise generated by bootsnap on `LoadError`.
66
+
67
+ # 1.9.4
68
+
69
+ * Ignore absolute paths in the loaded feature index. (#385)
70
+ This fixes a compatibility issue with Zeitwerk when Zeitwerk is loaded before bootsnap. It also should
71
+ reduce the memory usage and improve load performance of Zeitwerk managed files.
72
+
73
+ * Automatically invalidate the load path cache whenever the Ruby version change. (#387)
74
+ This is to avoid issues in case the same installation path is re-used for subsequent ruby patch releases.
75
+
76
+ # 1.9.3
77
+
78
+ * Only disable the compile cache for source files impacted by [Ruby 3.0.3 [Bug 18250]](https://bugs.ruby-lang.org/issues/18250).
79
+ This should keep the performance loss to a minimum.
80
+
81
+ # 1.9.2
82
+
83
+ * Disable compile cache if [Ruby 3.0.3's ISeq cache bug](https://bugs.ruby-lang.org/issues/18250) is detected.
84
+ AKA `iseq.rb:13 to_binary: wrong argument type false (expected Symbol)`
85
+ * Fix `Kernel.load` behavior: before `load 'a'` would load `a.rb` (and other tried extensions) and wouldn't load `a` unless `development_mode: true`, now only `a` would be loaded and files with extensions wouldn't be.
86
+
87
+ # 1.9.1
88
+
89
+ * Removed a forgotten debug statement in JSON precompilation.
90
+
91
+ # 1.9.0
92
+
93
+ * Added a compilation cache for `JSON.load_file`. (#370)
94
+
95
+ # 1.8.1
96
+
97
+ * Fixed support for older Psych. (#369)
98
+
99
+ # 1.8.0
100
+
101
+ * Improve support for Psych 4. (#368)
102
+
103
+ # 1.7.7
104
+
105
+ * Fix `require_relative` in evaled code on latest ruby 3.1.0-dev. (#366)
106
+
107
+ # 1.7.6
108
+
109
+ * Fix reliance on `set` to be required.
110
+ * Fix `Encoding::UndefinedConversionError` error for Rails applications when precompiling cache. (#364)
111
+
112
+ # 1.7.5
113
+
114
+ * Handle a regression of Ruby 2.7.3 causing Bootsnap to call the deprecated `untaint` method. (#360)
115
+ * Gracefully handle read-only file system as well as other errors preventing to persist the load path cache. (#358)
116
+
117
+ # 1.7.4
118
+
119
+ * Stop raising errors when encountering various file system errors. The cache is now best effort,
120
+ if somehow it can't be saved, bootsnap will gracefully fallback to the original operation (e.g. `Kernel.require`).
121
+ (#353, #177, #262)
122
+
123
+ # 1.7.3
124
+
125
+ * Disable YAML precompilation when encountering YAML tags. (#351)
126
+
3
127
  # 1.7.2
4
128
 
5
129
  * Fix compatibility with msgpack < 1. (#349)
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017 Shopify, Inc.
3
+ Copyright (c) 2017-present Shopify, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -41,7 +41,7 @@ getting progressively slower, this is almost certainly the cause.**
41
41
  It's technically possible to simply specify `gem 'bootsnap', require: 'bootsnap/setup'`, but it's
42
42
  important to load Bootsnap as early as possible to get maximum performance improvement.
43
43
 
44
- You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/setup.rb).
44
+ You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/setup.rb).
45
45
 
46
46
  If you are not using Rails, or if you are but want more control over things, add this to your
47
47
  application setup immediately after `require 'bundler/setup'` (i.e. as early as possible: the sooner
@@ -161,7 +161,7 @@ The only directories considered "stable" are things under the Ruby install prefi
161
161
  "volatile".
162
162
 
163
163
  In addition to the [`Bootsnap::LoadPathCache::Cache`
164
- source](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/load_path_cache/cache.rb),
164
+ source](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/load_path_cache/cache.rb),
165
165
  this diagram may help clarify how entry resolution works:
166
166
 
167
167
  ![How path searching works](https://cloud.githubusercontent.com/assets/3074765/25388270/670b5652-299b-11e7-87fb-975647f68981.png)
data/exe/bootsnap CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'bootsnap/cli'
4
+ require "bootsnap/cli"
5
5
  exit Bootsnap::CLI.new(ARGV).run
@@ -75,7 +75,7 @@ struct bs_cache_key {
75
75
  STATIC_ASSERT(sizeof(struct bs_cache_key) == KEY_SIZE);
76
76
 
77
77
  /* Effectively a schema version. Bumping invalidates all previous caches */
78
- static const uint32_t current_version = 3;
78
+ static const uint32_t current_version = 4;
79
79
 
80
80
  /* hash of e.g. "x86_64-darwin17", invalidating when ruby is recompiled on a
81
81
  * new OS ABI, etc. */
@@ -91,8 +91,7 @@ static mode_t current_umask;
91
91
  static VALUE rb_mBootsnap;
92
92
  static VALUE rb_mBootsnap_CompileCache;
93
93
  static VALUE rb_mBootsnap_CompileCache_Native;
94
- static VALUE rb_eBootsnap_CompileCache_Uncompilable;
95
- static ID uncompilable;
94
+ static VALUE rb_cBootsnap_CompileCache_UNCOMPILABLE;
96
95
  static ID instrumentation_method;
97
96
  static VALUE sym_miss;
98
97
  static VALUE sym_stale;
@@ -120,10 +119,8 @@ static uint32_t get_ruby_platform(void);
120
119
  * exception.
121
120
  */
122
121
  static int bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * output_data);
123
- static VALUE prot_storage_to_output(VALUE arg);
124
122
  static VALUE prot_input_to_output(VALUE arg);
125
123
  static void bs_input_to_output(VALUE handler, VALUE args, VALUE input_data, VALUE * output_data, int * exception_tag);
126
- static VALUE prot_input_to_storage(VALUE arg);
127
124
  static int bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data);
128
125
  struct s2o_data;
129
126
  struct i2o_data;
@@ -138,6 +135,12 @@ bs_rb_coverage_running(VALUE self)
138
135
  return RTEST(cov) ? Qtrue : Qfalse;
139
136
  }
140
137
 
138
+ static VALUE
139
+ bs_rb_get_path(VALUE self, VALUE fname)
140
+ {
141
+ return rb_get_path(fname);
142
+ }
143
+
141
144
  /*
142
145
  * Ruby C extensions are initialized by calling Init_<extname>.
143
146
  *
@@ -149,14 +152,17 @@ void
149
152
  Init_bootsnap(void)
150
153
  {
151
154
  rb_mBootsnap = rb_define_module("Bootsnap");
155
+
156
+ rb_define_singleton_method(rb_mBootsnap, "rb_get_path", bs_rb_get_path, 1);
157
+
152
158
  rb_mBootsnap_CompileCache = rb_define_module_under(rb_mBootsnap, "CompileCache");
153
159
  rb_mBootsnap_CompileCache_Native = rb_define_module_under(rb_mBootsnap_CompileCache, "Native");
154
- rb_eBootsnap_CompileCache_Uncompilable = rb_define_class_under(rb_mBootsnap_CompileCache, "Uncompilable", rb_eStandardError);
160
+ rb_cBootsnap_CompileCache_UNCOMPILABLE = rb_const_get(rb_mBootsnap_CompileCache, rb_intern("UNCOMPILABLE"));
161
+ rb_global_variable(&rb_cBootsnap_CompileCache_UNCOMPILABLE);
155
162
 
156
163
  current_ruby_revision = get_ruby_revision();
157
164
  current_ruby_platform = get_ruby_platform();
158
165
 
159
- uncompilable = rb_intern("__bootsnap_uncompilable__");
160
166
  instrumentation_method = rb_intern("_instrument");
161
167
 
162
168
  sym_miss = ID2SYM(rb_intern("miss"));
@@ -426,6 +432,7 @@ open_current_file(char * path, struct bs_cache_key * key, const char ** errno_pr
426
432
  #define ERROR_WITH_ERRNO -1
427
433
  #define CACHE_MISS -2
428
434
  #define CACHE_STALE -3
435
+ #define CACHE_UNCOMPILABLE -4
429
436
 
430
437
  /*
431
438
  * Read the cache key from the given fd, which must have position 0 (e.g.
@@ -464,8 +471,7 @@ open_cache_file(const char * path, struct bs_cache_key * key, const char ** errn
464
471
  fd = open(path, O_RDONLY);
465
472
  if (fd < 0) {
466
473
  *errno_provenance = "bs_fetch:open_cache_file:open";
467
- if (errno == ENOENT) return CACHE_MISS;
468
- return ERROR_WITH_ERRNO;
474
+ return CACHE_MISS;
469
475
  }
470
476
  #ifdef _WIN32
471
477
  setmode(fd, O_BINARY);
@@ -508,14 +514,14 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
508
514
  if (data_size > 100000000000) {
509
515
  *errno_provenance = "bs_fetch:fetch_cached_data:datasize";
510
516
  errno = EINVAL; /* because wtf? */
511
- ret = -1;
517
+ ret = ERROR_WITH_ERRNO;
512
518
  goto done;
513
519
  }
514
520
  data = ALLOC_N(char, data_size);
515
521
  nread = read(fd, data, data_size);
516
522
  if (nread < 0) {
517
523
  *errno_provenance = "bs_fetch:fetch_cached_data:read";
518
- ret = -1;
524
+ ret = ERROR_WITH_ERRNO;
519
525
  goto done;
520
526
  }
521
527
  if (nread != data_size) {
@@ -526,6 +532,10 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
526
532
  storage_data = rb_str_new(data, data_size);
527
533
 
528
534
  *exception_tag = bs_storage_to_output(handler, args, storage_data, output_data);
535
+ if (*output_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
536
+ ret = CACHE_UNCOMPILABLE;
537
+ goto done;
538
+ }
529
539
  ret = 0;
530
540
  done:
531
541
  if (data != NULL) xfree(data);
@@ -738,7 +748,15 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
738
748
  &output_data, &exception_tag, &errno_provenance
739
749
  );
740
750
  if (exception_tag != 0) goto raise;
741
- else if (res == CACHE_MISS || res == CACHE_STALE) valid_cache = 0;
751
+ else if (res == CACHE_UNCOMPILABLE) {
752
+ /* If fetch_cached_data returned `Uncompilable` we fallback to `input_to_output`
753
+ This happens if we have say, an unsafe YAML cache, but try to load it in safe mode */
754
+ if (bs_read_contents(current_fd, current_key.size, &contents, &errno_provenance) < 0) goto fail_errno;
755
+ input_data = rb_str_new(contents, current_key.size);
756
+ bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
757
+ if (exception_tag != 0) goto raise;
758
+ goto succeed;
759
+ } else if (res == CACHE_MISS || res == CACHE_STALE) valid_cache = 0;
742
760
  else if (res == ERROR_WITH_ERRNO) goto fail_errno;
743
761
  else if (!NIL_P(output_data)) goto succeed; /* fast-path, goal */
744
762
  }
@@ -755,7 +773,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
755
773
  if (exception_tag != 0) goto raise;
756
774
  /* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
757
775
  * to cache anything; just return input_to_output(input_data) */
758
- if (storage_data == uncompilable) {
776
+ if (storage_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
759
777
  bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
760
778
  if (exception_tag != 0) goto raise;
761
779
  goto succeed;
@@ -763,20 +781,30 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
763
781
  /* If storage_data isn't a string, we can't cache it */
764
782
  if (!RB_TYPE_P(storage_data, T_STRING)) goto invalid_type_storage_data;
765
783
 
766
- /* Write the cache key and storage_data to the cache directory */
767
- res = atomic_write_cache_file(cache_path, &current_key, storage_data, &errno_provenance);
768
- if (res < 0) goto fail_errno;
784
+ /* Attempt to write the cache key and storage_data to the cache directory.
785
+ * We do however ignore any failures to persist the cache, as it's better
786
+ * to move along, than to interrupt the process.
787
+ */
788
+ atomic_write_cache_file(cache_path, &current_key, storage_data, &errno_provenance);
769
789
 
770
790
  /* Having written the cache, now convert storage_data to output_data */
771
791
  exception_tag = bs_storage_to_output(handler, args, storage_data, &output_data);
772
792
  if (exception_tag != 0) goto raise;
773
793
 
774
- /* If output_data is nil, delete the cache entry and generate the output
775
- * using input_to_output */
776
- if (NIL_P(output_data)) {
794
+ if (output_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
795
+ /* If storage_to_output returned `Uncompilable` we fallback to `input_to_output` */
796
+ bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
797
+ if (exception_tag != 0) goto raise;
798
+ } else if (NIL_P(output_data)) {
799
+ /* If output_data is nil, delete the cache entry and generate the output
800
+ * using input_to_output */
777
801
  if (unlink(cache_path) < 0) {
778
- errno_provenance = "bs_fetch:unlink";
779
- goto fail_errno;
802
+ /* If the cache was already deleted, it might be that another process did it before us.
803
+ * No point raising an error */
804
+ if (errno != ENOENT) {
805
+ errno_provenance = "bs_fetch:unlink";
806
+ goto fail_errno;
807
+ }
780
808
  }
781
809
  bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
782
810
  if (exception_tag != 0) goto raise;
@@ -855,7 +883,7 @@ bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler)
855
883
 
856
884
  /* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
857
885
  * to cache anything; just return false */
858
- if (storage_data == uncompilable) {
886
+ if (storage_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
859
887
  goto fail;
860
888
  }
861
889
  /* If storage_data isn't a string, we can't cache it */
@@ -918,7 +946,7 @@ struct i2s_data {
918
946
  };
919
947
 
920
948
  static VALUE
921
- prot_storage_to_output(VALUE arg)
949
+ try_storage_to_output(VALUE arg)
922
950
  {
923
951
  struct s2o_data * data = (struct s2o_data *)arg;
924
952
  return rb_funcall(data->handler, rb_intern("storage_to_output"), 2, data->storage_data, data->args);
@@ -933,7 +961,7 @@ bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * outp
933
961
  .args = args,
934
962
  .storage_data = storage_data,
935
963
  };
936
- *output_data = rb_protect(prot_storage_to_output, (VALUE)&s2o_data, &state);
964
+ *output_data = rb_protect(try_storage_to_output, (VALUE)&s2o_data, &state);
937
965
  return state;
938
966
  }
939
967
 
@@ -962,22 +990,6 @@ try_input_to_storage(VALUE arg)
962
990
  return rb_funcall(data->handler, rb_intern("input_to_storage"), 2, data->input_data, data->pathval);
963
991
  }
964
992
 
965
- static VALUE
966
- rescue_input_to_storage(VALUE arg, VALUE e)
967
- {
968
- return uncompilable;
969
- }
970
-
971
- static VALUE
972
- prot_input_to_storage(VALUE arg)
973
- {
974
- struct i2s_data * data = (struct i2s_data *)arg;
975
- return rb_rescue2(
976
- try_input_to_storage, (VALUE)data,
977
- rescue_input_to_storage, Qnil,
978
- rb_eBootsnap_CompileCache_Uncompilable, 0);
979
- }
980
-
981
993
  static int
982
994
  bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data)
983
995
  {
@@ -987,6 +999,6 @@ bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval,
987
999
  .input_data = input_data,
988
1000
  .pathval = pathval,
989
1001
  };
990
- *storage_data = rb_protect(prot_input_to_storage, (VALUE)&i2s_data, &state);
1002
+ *storage_data = rb_protect(try_input_to_storage, (VALUE)&i2s_data, &state);
991
1003
  return state;
992
1004
  }
@@ -1,21 +1,23 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require("mkmf")
3
4
 
4
- if RUBY_ENGINE == 'ruby'
5
- $CFLAGS << ' -O3 '
6
- $CFLAGS << ' -std=c99'
5
+ if RUBY_ENGINE == "ruby"
6
+ $CFLAGS << " -O3 "
7
+ $CFLAGS << " -std=c99"
7
8
 
8
9
  # ruby.h has some -Wpedantic fails in some cases
9
10
  # (e.g. https://github.com/Shopify/bootsnap/issues/15)
10
- unless ['0', '', nil].include?(ENV['BOOTSNAP_PEDANTIC'])
11
- $CFLAGS << ' -Wall'
12
- $CFLAGS << ' -Werror'
13
- $CFLAGS << ' -Wextra'
14
- $CFLAGS << ' -Wpedantic'
11
+ unless ["0", "", nil].include?(ENV["BOOTSNAP_PEDANTIC"])
12
+ $CFLAGS << " -Wall"
13
+ $CFLAGS << " -Werror"
14
+ $CFLAGS << " -Wextra"
15
+ $CFLAGS << " -Wpedantic"
15
16
 
16
- $CFLAGS << ' -Wno-unused-parameter' # VALUE self has to be there but we don't care what it is.
17
- $CFLAGS << ' -Wno-keyword-macro' # hiding return
18
- $CFLAGS << ' -Wno-gcc-compat' # ruby.h 2.6.0 on macos 10.14, dunno
17
+ $CFLAGS << " -Wno-unused-parameter" # VALUE self has to be there but we don't care what it is.
18
+ $CFLAGS << " -Wno-keyword-macro" # hiding return
19
+ $CFLAGS << " -Wno-gcc-compat" # ruby.h 2.6.0 on macos 10.14, dunno
20
+ $CFLAGS << " -Wno-compound-token-split-by-macro"
19
21
  end
20
22
 
21
23
  create_makefile("bootsnap/bootsnap")
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bootsnap
3
4
  extend(self)
4
5
 
@@ -37,7 +37,11 @@ module Bootsnap
37
37
 
38
38
  def initialize(jobs)
39
39
  @jobs = jobs
40
- @pipe_out, @to_io = IO.pipe
40
+ @pipe_out, @to_io = IO.pipe(binmode: true)
41
+ # Set the writer encoding to binary since IO.pipe only sets it for the reader.
42
+ # https://github.com/rails/rails/issues/16514#issuecomment-52313290
43
+ @to_io.set_encoding(Encoding::BINARY)
44
+
41
45
  @pid = nil
42
46
  end
43
47
 
@@ -59,6 +63,7 @@ module Bootsnap
59
63
  loop do
60
64
  job, *args = Marshal.load(@pipe_out)
61
65
  return if job == :exit
66
+
62
67
  @jobs.fetch(job).call(*args)
63
68
  end
64
69
  rescue IOError