pitchfork 0.3.0 → 0.4.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.

Potentially problematic release.


This version of pitchfork might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e42e6177d834ad380a59378ccea33b4110b443975d913ca6bc66c84ee5abbdb
4
- data.tar.gz: 79ae3e1c674b3fa6b6bd78103d177d6593e8ce9239f4603450f300ad5685a827
3
+ metadata.gz: f37584c7333941059ab10086a74d1102b1969c2fefb7a759fc13f9e4f837891e
4
+ data.tar.gz: bc69759f0a53d98d81648ee60b833e6c49fd3f88d53f7ac319e9acff845c7cf1
5
5
  SHA512:
6
- metadata.gz: 1ff1761d7107bf62e2e7f31c7b1843ffe78eb99d650a8175ef0f9173f871499afb69b13407e9c70d80be4afd799a2c18243942318b92d5bd339bbbf591abb32b
7
- data.tar.gz: 7c49a7909dfd4d3405f66859a308700dd047aa360412a752831348a000ecd4be58d493856539e46b56825e74a7fd19ae81731344bef0a1cde16e3529134c94eb
6
+ metadata.gz: 69d796bf414bb4bf7b7867e61229fa12764ca12dd1aaf2b36a615c2b806a64aa665b4c1483147e6d39a4d49df340ad31406f0db294da52e9a8a5740b186233a9
7
+ data.tar.gz: 51dc5852d5bc26fbba0f1824beb76977653ae089d589e33a1d7defca89b9b2235f466c5fc59419f56d0944b6c5ee819e1f966e9c32eac3d79029d951a6071c38
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Unreleased
2
2
 
3
+ # 0.4.0
4
+
5
+ - Preserve the current thread when reforking.
6
+
3
7
  # 0.3.0
4
8
 
5
9
  - Renamed `after_promotion` in `after_mold_fork`.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pitchfork (0.3.0)
4
+ pitchfork (0.4.0)
5
5
  rack (>= 2.0)
6
6
  raindrops (~> 0.7)
7
7
 
@@ -606,7 +606,10 @@ module Pitchfork
606
606
  end
607
607
 
608
608
  unless client.closed? # rack.hijack may've close this for us
609
- client.shutdown # in case of fork() in Rack app
609
+ begin
610
+ client.shutdown # in case of fork() in Rack app
611
+ rescue Errno::ENOTCONN
612
+ end
610
613
  client.close # flush and uncork socket immediately, no keepalive
611
614
  end
612
615
  rescue => e
@@ -730,10 +733,15 @@ module Pitchfork
730
733
  mold.start_promotion(@control_socket[1])
731
734
  mold_loop(mold)
732
735
  end
733
- true
734
- ensure
736
+ rescue
737
+ # HACK: we need to call this on error or on no error, but not on throw
738
+ # hence why we don't use `ensure`
739
+ @promotion_lock.at_fork
740
+ raise
741
+ else
735
742
  @promotion_lock.at_fork # We let the spawned mold own the lock
736
743
  end
744
+ true
737
745
  end
738
746
 
739
747
  def mold_loop(mold)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pitchfork
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  module Const
6
6
  UNICORN_VERSION = '6.1.0'
7
7
  end
data/lib/pitchfork.rb CHANGED
@@ -121,21 +121,42 @@ module Pitchfork
121
121
  end
122
122
 
123
123
  def self.clean_fork(&block)
124
- # We fork from a thread to start with a clean stack.
125
- # If we didn't the base stack would grow after each refork
126
- # putting an effective limit on the number of generations.
127
- parent_thread = Thread.current
128
- Thread.new do
129
- current_thread = Thread.current
130
- # We copy over any thread state it might have
131
- parent_thread.keys.each do |key|
132
- current_thread[key] = parent_thread[key]
133
- end
134
- parent_thread.thread_variables.each do |variable|
135
- current_thread.thread_variable_set(variable, parent_thread.thread_variable_get(variable))
124
+ if pid = Process.fork
125
+ return pid
126
+ end
127
+
128
+ begin
129
+ # Pitchfork recursively refork the worker processes.
130
+ # Because of this we need to unwind the stack before resuming execution
131
+ # in the child, otherwise on each generation the available stack space would
132
+ # get smaller and smaller until it's basically 0.
133
+ #
134
+ # The very first version of this method used to call fork from a new
135
+ # thread, however this can cause issues with some native gems that rely on
136
+ # pthread_atfork(3) or pthread_mutex_lock(3), as the new main thread would
137
+ # now be different.
138
+ #
139
+ # A second version used to fork from a new fiber, but fibers have a much smaller
140
+ # stack space (https://bugs.ruby-lang.org/issues/3187), so it would break large applications.
141
+ #
142
+ # The latest version now use `throw` to unwind the stack after the fork, it however
143
+ # restrict it to be called only inside `handle_clean_fork`.
144
+ if Thread.current[:pitchfork_handle_clean_fork]
145
+ throw self, block
146
+ else
147
+ while block
148
+ block = catch(self) do
149
+ Thread.current[:pitchfork_handle_clean_fork] = true
150
+ block.call
151
+ nil
152
+ end
153
+ end
136
154
  end
137
- Process.fork(&block)
138
- end.value
155
+ rescue
156
+ abort
157
+ else
158
+ exit
159
+ end
139
160
  end
140
161
 
141
162
  def self.fork_sibling(&block)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pitchfork
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-24 00:00:00.000000000 Z
11
+ date: 2023-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: raindrops