pitchfork 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,7 +7,7 @@ module Pitchfork
7
7
  # releases of pitchfork. Knowledge of this class is generally not
8
8
  # not needed for most users of pitchfork.
9
9
  #
10
- # Some users may want to access it in the after_promotion/after_fork hooks.
10
+ # Some users may want to access it in the after_worker_fork/after_mold_fork hooks.
11
11
  # See the Pitchfork::Configurator RDoc for examples.
12
12
  class Worker
13
13
  # :stopdoc:
@@ -42,6 +42,10 @@ module Pitchfork
42
42
  @exiting
43
43
  end
44
44
 
45
+ def pending?
46
+ @master.nil?
47
+ end
48
+
45
49
  def outdated?
46
50
  CURRENT_GENERATION_DROP[0] > @generation
47
51
  end
@@ -50,22 +54,24 @@ module Pitchfork
50
54
  message.class.members.each do |member|
51
55
  send("#{member}=", message.public_send(member))
52
56
  end
53
-
54
- case message
55
- when Message::WorkerPromoted
56
- promoted!
57
- end
58
57
  end
59
58
 
60
59
  def register_to_master(control_socket)
61
60
  create_socketpair!
62
- message = Message::WorkerSpawned.new(@nr, Process.pid, generation, @master)
61
+ message = Message::WorkerSpawned.new(@nr, @pid, generation, @master)
63
62
  control_socket.sendmsg(message)
64
63
  @master.close
65
64
  end
66
65
 
67
- def declare_promotion(control_socket)
68
- message = Message::WorkerPromoted.new(@nr, Process.pid, generation)
66
+ def start_promotion(control_socket)
67
+ create_socketpair!
68
+ message = Message::MoldSpawned.new(@nr, @pid, generation, @master)
69
+ control_socket.sendmsg(message)
70
+ @master.close
71
+ end
72
+
73
+ def finish_promotion(control_socket)
74
+ message = Message::MoldReady.new(@nr, @pid, generation)
69
75
  control_socket.sendmsg(message)
70
76
  CURRENT_GENERATION_DROP[0] = @generation
71
77
  end
@@ -198,7 +204,7 @@ module Pitchfork
198
204
  end
199
205
 
200
206
  def after_fork_in_child
201
- @master.close
207
+ @master&.close
202
208
  end
203
209
 
204
210
  private
@@ -215,7 +221,7 @@ module Pitchfork
215
221
  else
216
222
  success = true
217
223
  end
218
- rescue Errno::EPIPE
224
+ rescue Errno::EPIPE, Errno::ECONNRESET
219
225
  # worker will be reaped soon
220
226
  end
221
227
  success
data/lib/pitchfork.rb CHANGED
@@ -57,15 +57,13 @@ module Pitchfork
57
57
  Object.const_get(File.basename(ru, '.rb').capitalize)
58
58
  end
59
59
 
60
- case ENV["RACK_ENV"]
61
- when "development"
62
- Rack::Builder.new do
63
- use(Rack::Lint)
64
- run inner_app
65
- end.to_app
66
- else
67
- inner_app
68
- end
60
+ Rack::Builder.new do
61
+ use(Rack::ContentLength)
62
+ use(Pitchfork::Chunked)
63
+ use(Rack::Lint) if ENV["RACK_ENV"] == "development"
64
+ use(Rack::TempfileReaper)
65
+ run inner_app
66
+ end.to_app
69
67
  end
70
68
  end
71
69
 
@@ -136,17 +134,53 @@ module Pitchfork
136
134
  parent_thread.thread_variables.each do |variable|
137
135
  current_thread.thread_variable_set(variable, parent_thread.thread_variable_get(variable))
138
136
  end
139
-
140
- fork(&block)
137
+ Process.fork(&block)
141
138
  end.value
142
139
  end
140
+
141
+ def self.fork_sibling(&block)
142
+ if REFORKING_AVAILABLE
143
+ # We double fork so that the new worker is re-attached back
144
+ # to the master.
145
+ # This requires either PR_SET_CHILD_SUBREAPER which is exclusive to Linux 3.4
146
+ # or the master to be PID 1.
147
+ if middle_pid = Process.fork # parent
148
+ # We need to wait(2) so that the middle process doesn't end up a zombie.
149
+ Process.wait(middle_pid)
150
+ else # first child
151
+ clean_fork(&block) # detach into a grand child
152
+ exit
153
+ end
154
+ else
155
+ clean_fork(&block)
156
+ end
157
+
158
+ nil # it's tricky to return the PID
159
+ end
160
+
161
+ def self.time_now(int = false)
162
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, int ? :second : :float_second)
163
+ end
143
164
  # :startdoc:
144
165
  end
145
166
  # :enddoc:
146
167
 
147
- %w(
148
- const socket_helper stream_input tee_input mem_info children message http_parser
149
- refork_condition configurator tmpio http_response worker http_server
150
- ).each do |s|
151
- require_relative "pitchfork/#{s}"
152
- end
168
+ require 'pitchfork/pitchfork_http'
169
+
170
+ Pitchfork::REFORKING_AVAILABLE = Pitchfork::CHILD_SUBREAPER_AVAILABLE || Process.pid == 1
171
+
172
+ require_relative "pitchfork/const"
173
+ require_relative "pitchfork/socket_helper"
174
+ require_relative "pitchfork/stream_input"
175
+ require_relative "pitchfork/tee_input"
176
+ require_relative "pitchfork/mem_info"
177
+ require_relative "pitchfork/children"
178
+ require_relative "pitchfork/message"
179
+ require_relative "pitchfork/chunked"
180
+ require_relative "pitchfork/http_parser"
181
+ require_relative "pitchfork/refork_condition"
182
+ require_relative "pitchfork/configurator"
183
+ require_relative "pitchfork/tmpio"
184
+ require_relative "pitchfork/http_response"
185
+ require_relative "pitchfork/worker"
186
+ require_relative "pitchfork/http_server"
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.2.0
4
+ version: 0.3.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-04-04 00:00:00.000000000 Z
11
+ date: 2023-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: raindrops
@@ -94,6 +94,7 @@ files:
94
94
  - lib/pitchfork.rb
95
95
  - lib/pitchfork/app/old_rails/static.rb
96
96
  - lib/pitchfork/children.rb
97
+ - lib/pitchfork/chunked.rb
97
98
  - lib/pitchfork/configurator.rb
98
99
  - lib/pitchfork/const.rb
99
100
  - lib/pitchfork/flock.rb
@@ -133,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
134
  - !ruby/object:Gem::Version
134
135
  version: '0'
135
136
  requirements: []
136
- rubygems_version: 3.4.6
137
+ rubygems_version: 3.4.10
137
138
  signing_key:
138
139
  specification_version: 4
139
140
  summary: Rack HTTP server for fast clients and Unix