puma 2.0.0.b4-java → 2.0.0.b7-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- data/History.txt +53 -0
- data/Manifest.txt +8 -3
- data/README.md +36 -5
- data/Rakefile +1 -1
- data/lib/puma/binder.rb +1 -1
- data/lib/puma/capistrano.rb +14 -12
- data/lib/puma/cli.rb +166 -25
- data/lib/puma/client.rb +9 -1
- data/lib/puma/configuration.rb +54 -13
- data/lib/puma/const.rb +7 -1
- data/lib/puma/jruby_restart.rb +4 -4
- data/lib/puma/minissl.rb +94 -92
- data/lib/puma/rack_default.rb +7 -0
- data/lib/puma/reactor.rb +28 -12
- data/lib/puma/server.rb +56 -27
- data/lib/puma/util.rb +9 -0
- data/puma.gemspec +10 -10
- data/test/test_config.rb +1 -1
- data/test/test_minissl.rb +5 -2
- data/test/test_puma_server.rb +37 -0
- data/tools/jungle/{README.md → init.d/README.md} +0 -0
- data/tools/jungle/{puma → init.d/puma} +0 -0
- data/tools/jungle/{run-puma → init.d/run-puma} +0 -0
- data/tools/jungle/upstart/README.md +61 -0
- data/tools/jungle/upstart/puma-manager.conf +31 -0
- data/tools/jungle/upstart/puma.conf +52 -0
- metadata +16 -8
data/lib/puma/client.rb
CHANGED
@@ -36,14 +36,22 @@ module Puma
|
|
36
36
|
@timeout_at = nil
|
37
37
|
|
38
38
|
@requests_served = 0
|
39
|
+
@hijacked = false
|
39
40
|
end
|
40
41
|
|
41
|
-
attr_reader :env, :to_io, :body, :io, :timeout_at, :ready
|
42
|
+
attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked
|
42
43
|
|
43
44
|
def inspect
|
44
45
|
"#<Puma::Client:0x#{object_id.to_s(16)} @ready=#{@ready.inspect}>"
|
45
46
|
end
|
46
47
|
|
48
|
+
# For the hijack protocol (allows us to just put the Client object
|
49
|
+
# into the env)
|
50
|
+
def call
|
51
|
+
@hijacked = true
|
52
|
+
env[HIJACK_IO] ||= @io
|
53
|
+
end
|
54
|
+
|
47
55
|
def set_timeout(val)
|
48
56
|
@timeout_at = Time.now + val
|
49
57
|
end
|
data/lib/puma/configuration.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Puma
|
2
|
+
|
3
|
+
# The CLI exports it's Configuration object here to allow
|
4
|
+
# apps to pick it up. An app needs to use it conditionally though
|
5
|
+
# since it is not set if the app is launched via another
|
6
|
+
# mechanism than the CLI class.
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :cli_config
|
10
|
+
end
|
11
|
+
|
2
12
|
class Configuration
|
3
13
|
DefaultRackup = "config.ru"
|
4
14
|
|
@@ -44,26 +54,39 @@ module Puma
|
|
44
54
|
end
|
45
55
|
end
|
46
56
|
|
57
|
+
# Injects the Configuration object into the env
|
58
|
+
class ConfigMiddleware
|
59
|
+
def initialize(config, app)
|
60
|
+
@config = config
|
61
|
+
@app = app
|
62
|
+
end
|
63
|
+
|
64
|
+
def call(env)
|
65
|
+
env[Const::PUMA_CONFIG] = @config
|
66
|
+
@app.call(env)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
47
70
|
# Load the specified rackup file, pull an options from
|
48
71
|
# the rackup file, and set @app.
|
49
72
|
#
|
50
73
|
def app
|
51
|
-
|
52
|
-
return app
|
53
|
-
end
|
74
|
+
app = @options[:app]
|
54
75
|
|
55
|
-
|
76
|
+
unless app
|
77
|
+
path = @options[:rackup] || DefaultRackup
|
56
78
|
|
57
|
-
|
58
|
-
|
59
|
-
|
79
|
+
unless File.exists?(path)
|
80
|
+
raise "Missing rackup file '#{path}'"
|
81
|
+
end
|
60
82
|
|
61
|
-
|
62
|
-
|
83
|
+
app, options = Rack::Builder.parse_file path
|
84
|
+
@options.merge! options
|
63
85
|
|
64
|
-
|
65
|
-
|
66
|
-
|
86
|
+
options.each do |key,val|
|
87
|
+
if key.to_s[0,4] == "bind"
|
88
|
+
@options[:binds] << val
|
89
|
+
end
|
67
90
|
end
|
68
91
|
end
|
69
92
|
|
@@ -72,7 +95,7 @@ module Puma
|
|
72
95
|
app = Rack::CommonLogger.new(app, logger)
|
73
96
|
end
|
74
97
|
|
75
|
-
return app
|
98
|
+
return ConfigMiddleware.new(self, app)
|
76
99
|
end
|
77
100
|
|
78
101
|
def setup_random_token
|
@@ -176,6 +199,14 @@ module Puma
|
|
176
199
|
@options[:on_restart] << blk
|
177
200
|
end
|
178
201
|
|
202
|
+
# Command to use to restart puma. This should be just how to
|
203
|
+
# load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
|
204
|
+
# to puma, as those are the same as the original process.
|
205
|
+
#
|
206
|
+
def restart_command(cmd)
|
207
|
+
@options[:request_cmd] = cmd
|
208
|
+
end
|
209
|
+
|
179
210
|
# Store the pid of the server in the file at +path+.
|
180
211
|
def pidfile(path)
|
181
212
|
@options[:pidfile] = path
|
@@ -234,9 +265,19 @@ module Puma
|
|
234
265
|
@options[:workers] = count.to_i
|
235
266
|
end
|
236
267
|
|
268
|
+
# *Cluster mode only* Code to run when a worker boots to setup
|
269
|
+
# the process before booting the app.
|
270
|
+
#
|
271
|
+
# This can be called multiple times to add hooks.
|
272
|
+
#
|
273
|
+
def on_worker_boot(&block)
|
274
|
+
@options[:worker_boot] << block
|
275
|
+
end
|
276
|
+
|
237
277
|
# The directory to operate out of.
|
238
278
|
def directory(dir)
|
239
279
|
@options[:directory] = dir.to_s
|
280
|
+
@options[:worker_directory] = dir.to_s
|
240
281
|
end
|
241
282
|
end
|
242
283
|
end
|
data/lib/puma/const.rb
CHANGED
@@ -28,7 +28,7 @@ module Puma
|
|
28
28
|
# too taxing on performance.
|
29
29
|
module Const
|
30
30
|
|
31
|
-
PUMA_VERSION = VERSION = "2.0.0.
|
31
|
+
PUMA_VERSION = VERSION = "2.0.0.b7".freeze
|
32
32
|
|
33
33
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
34
34
|
|
@@ -101,6 +101,7 @@ module Puma
|
|
101
101
|
SERVER_PORT = "SERVER_PORT".freeze
|
102
102
|
HTTP_HOST = "HTTP_HOST".freeze
|
103
103
|
PORT_80 = "80".freeze
|
104
|
+
PORT_443 = "443".freeze
|
104
105
|
LOCALHOST = "localhost".freeze
|
105
106
|
|
106
107
|
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
|
@@ -119,6 +120,7 @@ module Puma
|
|
119
120
|
RACK_URL_SCHEME = "rack.url_scheme".freeze
|
120
121
|
RACK_AFTER_REPLY = "rack.after_reply".freeze
|
121
122
|
PUMA_SOCKET = "puma.socket".freeze
|
123
|
+
PUMA_CONFIG = "puma.config".freeze
|
122
124
|
|
123
125
|
HTTP = "http".freeze
|
124
126
|
HTTPS = "https".freeze
|
@@ -147,5 +149,9 @@ module Puma
|
|
147
149
|
COLON = ": ".freeze
|
148
150
|
|
149
151
|
NEWLINE = "\n".freeze
|
152
|
+
|
153
|
+
HIJACK_P = "rack.hijack?".freeze
|
154
|
+
HIJACK = "rack.hijack".freeze
|
155
|
+
HIJACK_IO = "rack.hijack_io".freeze
|
150
156
|
end
|
151
157
|
end
|
data/lib/puma/jruby_restart.rb
CHANGED
@@ -8,12 +8,12 @@ module Puma
|
|
8
8
|
attach_function :execlp, [:string, :varargs], :int
|
9
9
|
attach_function :chdir, [:string], :int
|
10
10
|
|
11
|
-
def self.chdir_exec(dir,
|
11
|
+
def self.chdir_exec(dir, argv)
|
12
12
|
chdir(dir)
|
13
|
-
argv.
|
13
|
+
cmd = argv.first
|
14
14
|
argv = ([:string] * argv.size).zip(argv).flatten
|
15
|
-
argv
|
16
|
-
argv <<
|
15
|
+
argv << :string
|
16
|
+
argv << nil
|
17
17
|
execlp(cmd, *argv)
|
18
18
|
raise SystemCallError.new(FFI.errno)
|
19
19
|
end
|
data/lib/puma/minissl.rb
CHANGED
@@ -1,137 +1,139 @@
|
|
1
|
-
module Puma
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Puma
|
2
|
+
module MiniSSL
|
3
|
+
class Socket
|
4
|
+
def initialize(socket, engine)
|
5
|
+
@socket = socket
|
6
|
+
@engine = engine
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def to_io
|
10
|
+
@socket
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def readpartial(size)
|
14
|
+
while true
|
15
|
+
output = @engine.read
|
16
|
+
return output if output
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
data = @socket.readpartial(size)
|
19
|
+
@engine.inject(data)
|
20
|
+
output = @engine.read
|
20
21
|
|
21
|
-
|
22
|
+
return output if output
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
while neg_data = @engine.extract
|
25
|
+
@socket.write neg_data
|
26
|
+
end
|
25
27
|
end
|
26
28
|
end
|
27
|
-
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def read_nonblock(size)
|
31
|
+
while true
|
32
|
+
output = @engine.read
|
33
|
+
return output if output
|
33
34
|
|
34
|
-
|
35
|
+
data = @socket.read_nonblock(size)
|
35
36
|
|
36
|
-
|
37
|
-
|
37
|
+
@engine.inject(data)
|
38
|
+
output = @engine.read
|
38
39
|
|
39
|
-
|
40
|
+
return output if output
|
40
41
|
|
41
|
-
|
42
|
-
|
42
|
+
while neg_data = @engine.extract
|
43
|
+
@socket.write neg_data
|
44
|
+
end
|
43
45
|
end
|
44
46
|
end
|
45
|
-
end
|
46
47
|
|
47
|
-
|
48
|
-
|
48
|
+
def write(data)
|
49
|
+
need = data.size
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
while true
|
52
|
+
wrote = @engine.write data
|
53
|
+
enc = @engine.extract
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
if enc
|
56
|
+
@socket.syswrite enc
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
+
need -= wrote
|
59
60
|
|
60
|
-
|
61
|
+
return data.size if need == 0
|
61
62
|
|
62
|
-
|
63
|
+
data = data[need..-1]
|
64
|
+
end
|
63
65
|
end
|
64
|
-
end
|
65
66
|
|
66
|
-
|
67
|
+
alias_method :syswrite, :write
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
def flush
|
70
|
+
@socket.flush
|
71
|
+
end
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
def close
|
74
|
+
@socket.close
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
77
|
+
def peeraddr
|
78
|
+
@socket.peeraddr
|
79
|
+
end
|
78
80
|
end
|
79
|
-
end
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
class Context
|
83
|
+
attr_accessor :verify_mode
|
83
84
|
|
84
|
-
|
85
|
-
|
85
|
+
attr_reader :key
|
86
|
+
attr_reader :cert
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
def key=(key)
|
89
|
+
raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
|
90
|
+
@key = key
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
93
|
+
def cert=(cert)
|
94
|
+
raise ArgumentError, "No such cert file '#{cert}'" unless File.exist? cert
|
95
|
+
@cert = cert
|
96
|
+
end
|
95
97
|
end
|
96
|
-
end
|
97
98
|
|
98
|
-
|
99
|
-
|
99
|
+
VERIFY_NONE = 0
|
100
|
+
VERIFY_PEER = 1
|
100
101
|
|
101
|
-
|
102
|
+
#if defined?(JRUBY_VERSION)
|
102
103
|
#class Engine
|
103
|
-
|
104
|
-
|
105
|
-
|
104
|
+
#def self.server(key, cert)
|
105
|
+
#new(key, cert)
|
106
|
+
#end
|
107
|
+
#end
|
106
108
|
#end
|
107
|
-
#end
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
110
|
+
class Server
|
111
|
+
def initialize(socket, ctx)
|
112
|
+
@socket = socket
|
113
|
+
@ctx = ctx
|
114
|
+
end
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
116
|
+
def to_io
|
117
|
+
@socket
|
118
|
+
end
|
118
119
|
|
119
|
-
|
120
|
-
|
121
|
-
|
120
|
+
def accept
|
121
|
+
io = @socket.accept
|
122
|
+
engine = Engine.server @ctx.key, @ctx.cert
|
122
123
|
|
123
|
-
|
124
|
-
|
124
|
+
Socket.new io, engine
|
125
|
+
end
|
125
126
|
|
126
|
-
|
127
|
-
|
128
|
-
|
127
|
+
def accept_nonblock
|
128
|
+
io = @socket.accept_nonblock
|
129
|
+
engine = Engine.server @ctx.key, @ctx.cert
|
129
130
|
|
130
|
-
|
131
|
-
|
131
|
+
Socket.new io, engine
|
132
|
+
end
|
132
133
|
|
133
|
-
|
134
|
-
|
134
|
+
def close
|
135
|
+
@socket.close
|
136
|
+
end
|
135
137
|
end
|
136
138
|
end
|
137
139
|
end
|
data/lib/puma/reactor.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'puma/util'
|
2
|
+
|
1
3
|
module Puma
|
2
4
|
class Reactor
|
3
5
|
DefaultSleepFor = 5
|
@@ -8,7 +10,7 @@ module Puma
|
|
8
10
|
@app_pool = app_pool
|
9
11
|
|
10
12
|
@mutex = Mutex.new
|
11
|
-
@ready, @trigger =
|
13
|
+
@ready, @trigger = Puma::Util.pipe
|
12
14
|
@input = []
|
13
15
|
@sleep_for = DefaultSleepFor
|
14
16
|
@timeouts = []
|
@@ -48,7 +50,9 @@ module Puma
|
|
48
50
|
# list or we'll accidentally close the socket when
|
49
51
|
# it's in use!
|
50
52
|
if c.timeout_at
|
51
|
-
@
|
53
|
+
@mutex.synchronize do
|
54
|
+
@timeouts.delete c
|
55
|
+
end
|
52
56
|
end
|
53
57
|
|
54
58
|
begin
|
@@ -76,19 +80,24 @@ module Puma
|
|
76
80
|
end
|
77
81
|
|
78
82
|
unless @timeouts.empty?
|
79
|
-
|
83
|
+
@mutex.synchronize do
|
84
|
+
now = Time.now
|
80
85
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
86
|
+
while @timeouts.first.timeout_at < now
|
87
|
+
c = @timeouts.shift
|
88
|
+
sockets.delete c
|
89
|
+
c.close
|
85
90
|
|
86
|
-
|
87
|
-
|
91
|
+
break if @timeouts.empty?
|
92
|
+
end
|
88
93
|
|
89
|
-
|
94
|
+
calculate_sleep
|
95
|
+
end
|
90
96
|
end
|
91
97
|
end
|
98
|
+
ensure
|
99
|
+
@trigger.close
|
100
|
+
@ready.close
|
92
101
|
end
|
93
102
|
|
94
103
|
def run_in_thread
|
@@ -135,11 +144,18 @@ module Puma
|
|
135
144
|
|
136
145
|
# Close all watched sockets and clear them from being watched
|
137
146
|
def clear!
|
138
|
-
|
147
|
+
begin
|
148
|
+
@trigger << "c"
|
149
|
+
rescue IOError
|
150
|
+
end
|
139
151
|
end
|
140
152
|
|
141
153
|
def shutdown
|
142
|
-
|
154
|
+
begin
|
155
|
+
@trigger << "!"
|
156
|
+
rescue IOError
|
157
|
+
end
|
158
|
+
|
143
159
|
@thread.join
|
144
160
|
end
|
145
161
|
end
|