pitchfork 0.3.0 → 0.4.0

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: 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