hyperion-rb 2.16.1 → 2.16.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: 8ee8566aa14b81d85a43cb2bdfad406f4f026836d230efcee7d4c386f98a1af8
4
- data.tar.gz: 0c982adc33ba39f5e3b50179edaea24e9c82de40e6b11220f024a9d663e2e434
3
+ metadata.gz: 85ee19dc8b680c83c849964653ce228ebb94cd65a430f43ed13653ba36f06190
4
+ data.tar.gz: 4a02a074020c814d3036099d9ff996dd7098e704b03c4484e8a86e8320b60c65
5
5
  SHA512:
6
- metadata.gz: 772d23dde2abe5b97ec1e943f46e7744fd932d57e8e8488a9374fdcf42dec6c2479d315cdd7dc6b389d5f68c83fe8973acad0940108092009c81d8c7e8dbbd4f
7
- data.tar.gz: abed58d154aea89829e1b9ef74c31027fa15d451ea51ed13c6736ae452e1fd06bf030dcfc5bc9bfa83dcb413b87e365e6c600bf62ac875f3fec488b54b58e39a
6
+ metadata.gz: b614b52474052c37ba35d8d5bb633227b4b05112c617e71893e3a8c28d6d10f4ca406478a024238a841bc9aed5cc86df1ebcca5b9c8b9d21ab315ddfc8dcf996
7
+ data.tar.gz: aef147c323a1ca872d6e8467e15ff50a58fe8ae81a926b7fb87362736d5072824b785bdf682341fa4da858c7887aada193199a91f320ad3b88cafe55ee267ae5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.16.2 — 2026-05-04
4
+
5
+ ### 2.16.2-A — macOS Obj-C fork-safety: re-exec, not just ENV write
6
+
7
+ **Why.** 2.16.1's `ENV['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] ||= 'YES'`
8
+ in `bin/hyperion` and `lib/hyperion.rb` did not actually stop the
9
+ crash. The Obj-C runtime caches that env var's value at **dyld init**
10
+ — before any Ruby code runs. By the time `bin/hyperion`'s first
11
+ line executes, the runtime has already decided whether the post-fork
12
+ check fires. Setting the var from Ruby is observable to `ENV.fetch`
13
+ and inherited by `Process.fork` children via the kernel's env
14
+ duplication, but the Obj-C runtime's own check ignores the late
15
+ write. Workers continued to crash on `+[NSCharacterSet initialize]`
16
+ in fork children after a 2.16.1 master spawned them.
17
+
18
+ **What 2.16.2-A ships.** `bin/hyperion` now **re-execs itself** with
19
+ the env var set when launched on `darwin` without it:
20
+
21
+ ```ruby
22
+ if RUBY_PLATFORM.include?('darwin') && ENV['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'].nil?
23
+ ENV['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] = 'YES'
24
+ exec(RbConfig.ruby, __FILE__, *ARGV)
25
+ end
26
+ ```
27
+
28
+ `exec` replaces the current process image; dyld of the new image
29
+ reads `OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES` from the inherited
30
+ environment and the runtime's fork-safety check honours it for the
31
+ master and every worker forked from it. Operators who have already
32
+ set the var explicitly (shell export, Foreman's `.env` load,
33
+ Dockerfile `ENV`) skip the re-exec — the `nil?` guard preserves
34
+ deliberate `=NO` settings if anyone has a reason for those. The
35
+ operator-facing shell call (`bundle exec hyperion …`) sees a single
36
+ child and a single exit status; the re-exec is invisible.
37
+
38
+ `lib/hyperion.rb`'s 2.16.1 `ENV ||=` line is removed: it was
39
+ misleading (couldn't work for the current process anyway).
40
+ Programmatic users embedding Hyperion via `require 'hyperion'`
41
+ without `bin/hyperion` on macOS must set the env var themselves in
42
+ the shell or wrapper before launching Ruby — same as before 2.16.1.
43
+
44
+ **Verification.**
45
+
46
+ - `bin/check` green.
47
+ - Fresh `bundle exec hyperion -C config/hyperion.rb config.ru` against
48
+ the same Rails 8.1 app that reproduced the 2.16.1 crash loop:
49
+ master + workers boot cleanly; no `NSCharacterSet`-init crash; no
50
+ worker respawn churn; sequential curls return 200 OK.
51
+
3
52
  ## 2.16.1 — 2026-05-04
4
53
 
5
54
  ### 2.16.1-A — macOS Obj-C fork-safety guard
data/bin/hyperion CHANGED
@@ -1,14 +1,31 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # 2.16.1 — macOS fork-safety. The Obj-C runtime's post-fork sanity check
5
- # crashes any worker that touches a Foundation class which was mid-init
6
- # in the master at fork time (e.g. NSCharacterSet, common as a side-effect
7
- # of OpenSSL / system-resolver loads). The escape hatch is the env var
8
- # below; it must be set before Foundation classes load. Set on darwin
9
- # unconditionally no-op elsewhere. `||=` so an operator who has set
10
- # it explicitly (e.g. to `NO`) is honoured.
11
- ENV['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] ||= 'YES' if RUBY_PLATFORM.include?('darwin')
4
+ # 2.16.2 — macOS fork-safety. The Obj-C runtime caches the value of
5
+ # `OBJC_DISABLE_INITIALIZE_FORK_SAFETY` at dyld init time, BEFORE any
6
+ # Ruby code runs. Setting `ENV[...]` from Ruby is observable to
7
+ # `Process.fork`'s child via inheritance, but the runtime's own
8
+ # fork-safety check has already locked in its decision based on the
9
+ # env it saw at process launch. So a Ruby-side `ENV[...] = 'YES'`
10
+ # does not stop the post-fork crash:
11
+ # "+[NSCharacterSet initialize] may have been in progress in another
12
+ # thread when fork() was called. We cannot safely call it or ignore
13
+ # it in the fork() child process. Crashing instead."
14
+ #
15
+ # The reliable way to get the var into dyld's view is to re-exec the
16
+ # Ruby process with it set. Once the new process starts, dyld picks
17
+ # up the env var and the runtime's fork-safety check honours it.
18
+ # `exec` replaces the current image so the wrapper shell call (e.g.
19
+ # `bundle exec hyperion …`) sees a single child process and a single
20
+ # exit status — no double accounting from the operator's side.
21
+ #
22
+ # Operators who've already set the var explicitly (in their shell, in
23
+ # Foreman's .env load, in a Dockerfile ENV) skip this re-exec — we
24
+ # only re-exec when the var is unset.
25
+ if RUBY_PLATFORM.include?('darwin') && ENV['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'].nil?
26
+ ENV['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] = 'YES'
27
+ exec(RbConfig.ruby, __FILE__, *ARGV)
28
+ end
12
29
 
13
30
  $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
14
31
  require 'hyperion/cli'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hyperion
4
- VERSION = '2.16.1'
4
+ VERSION = '2.16.2'
5
5
  end
data/lib/hyperion.rb CHANGED
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # 2.16.1 macOS fork-safety. Mirrors the guard at the top of
4
- # `bin/hyperion` so programmatic `require 'hyperion'` (specs,
5
- # embedded uses) gets the same workaround. The Obj-C runtime's
6
- # post-fork check crashes workers that touch a Foundation class
7
- # which was mid-init in the master at fork time (NSCharacterSet
8
- # is a frequent victim it loads transitively via OpenSSL / system
9
- # resolver paths). `||=` so an operator who has set the var
10
- # explicitly is honoured. No-op on non-darwin platforms.
11
- ENV['OBJC_DISABLE_INITIALIZE_FORK_SAFETY'] ||= 'YES' if RUBY_PLATFORM.include?('darwin')
3
+ # Note: macOS Obj-C fork-safety is handled in `bin/hyperion` (re-exec
4
+ # with `OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES`). It cannot be handled
5
+ # from this file: setting `ENV[...]` from Ruby runs after dyld has
6
+ # already cached its decision, so by the time `require 'hyperion'`
7
+ # fires, the runtime's fork-safety check has locked in. Operators
8
+ # embedding Hyperion programmatically (no `bin/hyperion`) on macOS
9
+ # must set the env var in their shell or wrapper before exec.
12
10
 
13
11
  require_relative 'hyperion/version'
14
12
  require_relative 'hyperion/logger'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyperion-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.16.1
4
+ version: 2.16.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Lobanov