puma-simon 3.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/.github/issue_template.md +20 -0
  3. data/.gitignore +18 -0
  4. data/.hoeignore +12 -0
  5. data/.travis.yml +29 -0
  6. data/DEPLOYMENT.md +91 -0
  7. data/Gemfile +12 -0
  8. data/History.md +1254 -0
  9. data/LICENSE +26 -0
  10. data/Manifest.txt +78 -0
  11. data/README.md +353 -0
  12. data/Rakefile +158 -0
  13. data/Release.md +9 -0
  14. data/bin/puma +10 -0
  15. data/bin/puma-wild +31 -0
  16. data/bin/pumactl +12 -0
  17. data/docs/nginx.md +80 -0
  18. data/docs/signals.md +43 -0
  19. data/docs/systemd.md +197 -0
  20. data/examples/CA/cacert.pem +23 -0
  21. data/examples/CA/newcerts/cert_1.pem +19 -0
  22. data/examples/CA/newcerts/cert_2.pem +19 -0
  23. data/examples/CA/private/cakeypair.pem +30 -0
  24. data/examples/CA/serial +1 -0
  25. data/examples/config.rb +200 -0
  26. data/examples/plugins/redis_stop_puma.rb +46 -0
  27. data/examples/puma/cert_puma.pem +19 -0
  28. data/examples/puma/client-certs/ca.crt +19 -0
  29. data/examples/puma/client-certs/ca.key +27 -0
  30. data/examples/puma/client-certs/client.crt +19 -0
  31. data/examples/puma/client-certs/client.key +27 -0
  32. data/examples/puma/client-certs/client_expired.crt +19 -0
  33. data/examples/puma/client-certs/client_expired.key +27 -0
  34. data/examples/puma/client-certs/client_unknown.crt +19 -0
  35. data/examples/puma/client-certs/client_unknown.key +27 -0
  36. data/examples/puma/client-certs/generate.rb +78 -0
  37. data/examples/puma/client-certs/keystore.jks +0 -0
  38. data/examples/puma/client-certs/server.crt +19 -0
  39. data/examples/puma/client-certs/server.key +27 -0
  40. data/examples/puma/client-certs/server.p12 +0 -0
  41. data/examples/puma/client-certs/unknown_ca.crt +19 -0
  42. data/examples/puma/client-certs/unknown_ca.key +27 -0
  43. data/examples/puma/csr_puma.pem +11 -0
  44. data/examples/puma/keystore.jks +0 -0
  45. data/examples/puma/puma_keypair.pem +15 -0
  46. data/examples/qc_config.rb +13 -0
  47. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  48. data/ext/puma_http11/ext_help.h +15 -0
  49. data/ext/puma_http11/extconf.rb +15 -0
  50. data/ext/puma_http11/http11_parser.c +1069 -0
  51. data/ext/puma_http11/http11_parser.h +65 -0
  52. data/ext/puma_http11/http11_parser.java.rl +161 -0
  53. data/ext/puma_http11/http11_parser.rl +147 -0
  54. data/ext/puma_http11/http11_parser_common.rl +54 -0
  55. data/ext/puma_http11/io_buffer.c +155 -0
  56. data/ext/puma_http11/mini_ssl.c +457 -0
  57. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  58. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +473 -0
  59. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +339 -0
  60. data/ext/puma_http11/puma_http11.c +500 -0
  61. data/gemfiles/2.1-Gemfile +12 -0
  62. data/lib/puma.rb +15 -0
  63. data/lib/puma/accept_nonblock.rb +23 -0
  64. data/lib/puma/app/status.rb +66 -0
  65. data/lib/puma/binder.rb +402 -0
  66. data/lib/puma/cli.rb +220 -0
  67. data/lib/puma/client.rb +434 -0
  68. data/lib/puma/cluster.rb +510 -0
  69. data/lib/puma/commonlogger.rb +106 -0
  70. data/lib/puma/compat.rb +14 -0
  71. data/lib/puma/configuration.rb +364 -0
  72. data/lib/puma/const.rb +224 -0
  73. data/lib/puma/control_cli.rb +259 -0
  74. data/lib/puma/convenient.rb +23 -0
  75. data/lib/puma/daemon_ext.rb +31 -0
  76. data/lib/puma/delegation.rb +11 -0
  77. data/lib/puma/detect.rb +13 -0
  78. data/lib/puma/dsl.rb +486 -0
  79. data/lib/puma/events.rb +152 -0
  80. data/lib/puma/io_buffer.rb +7 -0
  81. data/lib/puma/java_io_buffer.rb +45 -0
  82. data/lib/puma/jruby_restart.rb +83 -0
  83. data/lib/puma/launcher.rb +410 -0
  84. data/lib/puma/minissl.rb +221 -0
  85. data/lib/puma/null_io.rb +42 -0
  86. data/lib/puma/plugin.rb +115 -0
  87. data/lib/puma/plugin/tmp_restart.rb +35 -0
  88. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  89. data/lib/puma/rack/builder.rb +298 -0
  90. data/lib/puma/rack/urlmap.rb +91 -0
  91. data/lib/puma/rack_default.rb +7 -0
  92. data/lib/puma/reactor.rb +210 -0
  93. data/lib/puma/runner.rb +171 -0
  94. data/lib/puma/server.rb +949 -0
  95. data/lib/puma/single.rb +112 -0
  96. data/lib/puma/state_file.rb +29 -0
  97. data/lib/puma/tcp_logger.rb +39 -0
  98. data/lib/puma/thread_pool.rb +297 -0
  99. data/lib/puma/util.rb +128 -0
  100. data/lib/rack/handler/puma.rb +78 -0
  101. data/puma.gemspec +52 -0
  102. data/test/ab_rs.rb +22 -0
  103. data/test/config.rb +2 -0
  104. data/test/config/app.rb +9 -0
  105. data/test/config/plugin.rb +1 -0
  106. data/test/config/settings.rb +2 -0
  107. data/test/config/state_file_testing_config.rb +14 -0
  108. data/test/hello-bind.ru +2 -0
  109. data/test/hello-delay.ru +3 -0
  110. data/test/hello-map.ru +3 -0
  111. data/test/hello-post.ru +4 -0
  112. data/test/hello-stuck.ru +1 -0
  113. data/test/hello-tcp.ru +5 -0
  114. data/test/hello.ru +1 -0
  115. data/test/hijack.ru +6 -0
  116. data/test/hijack2.ru +5 -0
  117. data/test/lobster.ru +4 -0
  118. data/test/shell/run.sh +24 -0
  119. data/test/shell/t1.rb +19 -0
  120. data/test/shell/t1_conf.rb +3 -0
  121. data/test/shell/t2.rb +17 -0
  122. data/test/shell/t2_conf.rb +6 -0
  123. data/test/shell/t3.rb +25 -0
  124. data/test/shell/t3_conf.rb +5 -0
  125. data/test/slow.ru +4 -0
  126. data/test/ssl_config.rb +4 -0
  127. data/test/test_app_status.rb +93 -0
  128. data/test/test_binder.rb +31 -0
  129. data/test/test_cli.rb +209 -0
  130. data/test/test_config.rb +95 -0
  131. data/test/test_events.rb +161 -0
  132. data/test/test_helper.rb +50 -0
  133. data/test/test_http10.rb +27 -0
  134. data/test/test_http11.rb +186 -0
  135. data/test/test_integration.rb +247 -0
  136. data/test/test_iobuffer.rb +39 -0
  137. data/test/test_minissl.rb +29 -0
  138. data/test/test_null_io.rb +49 -0
  139. data/test/test_persistent.rb +245 -0
  140. data/test/test_puma_server.rb +626 -0
  141. data/test/test_puma_server_ssl.rb +222 -0
  142. data/test/test_rack_handler.rb +57 -0
  143. data/test/test_rack_server.rb +138 -0
  144. data/test/test_tcp_logger.rb +39 -0
  145. data/test/test_tcp_rack.rb +36 -0
  146. data/test/test_thread_pool.rb +250 -0
  147. data/test/test_unix_socket.rb +35 -0
  148. data/test/test_web_server.rb +88 -0
  149. data/tools/jungle/README.md +9 -0
  150. data/tools/jungle/init.d/README.md +59 -0
  151. data/tools/jungle/init.d/puma +421 -0
  152. data/tools/jungle/init.d/run-puma +18 -0
  153. data/tools/jungle/upstart/README.md +61 -0
  154. data/tools/jungle/upstart/puma-manager.conf +31 -0
  155. data/tools/jungle/upstart/puma.conf +69 -0
  156. data/tools/trickletest.rb +45 -0
  157. metadata +297 -0
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "hoe"
4
+ gem "hoe-git"
5
+ gem "hoe-ignore"
6
+ gem "rdoc"
7
+ gem "rake-compiler"
8
+
9
+ gem "rack", "~> 1.6"
10
+ gem "minitest", '~> 5.9'
11
+
12
+ gem "jruby-openssl", :platform => "jruby"
@@ -0,0 +1,15 @@
1
+ # Standard libraries
2
+ require 'socket'
3
+ require 'tempfile'
4
+ require 'time'
5
+ require 'etc'
6
+ require 'uri'
7
+ require 'stringio'
8
+
9
+ require 'thread'
10
+
11
+ module Puma
12
+ autoload :Const, 'puma/const'
13
+ autoload :Server, 'puma/server'
14
+ autoload :Launcher, 'puma/launcher'
15
+ end
@@ -0,0 +1,23 @@
1
+ require 'openssl'
2
+
3
+ module OpenSSL
4
+ module SSL
5
+ class SSLServer
6
+ unless public_method_defined? :accept_nonblock
7
+ def accept_nonblock
8
+ sock = @svr.accept_nonblock
9
+
10
+ begin
11
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
12
+ ssl.sync_close = true
13
+ ssl.accept if @start_immediately
14
+ ssl
15
+ rescue SSLError => ex
16
+ sock.close
17
+ raise ex
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,66 @@
1
+ module Puma
2
+ module App
3
+ class Status
4
+ def initialize(cli)
5
+ @cli = cli
6
+ @auth_token = nil
7
+ end
8
+ OK_STATUS = '{ "status": "ok" }'.freeze
9
+
10
+ attr_accessor :auth_token
11
+
12
+ def authenticate(env)
13
+ return true unless @auth_token
14
+ env['QUERY_STRING'].to_s.split(/&;/).include?("token=#{@auth_token}")
15
+ end
16
+
17
+ def rack_response(status, body, content_type='application/json')
18
+ headers = {
19
+ 'Content-Type' => content_type,
20
+ 'Content-Length' => body.bytesize.to_s
21
+ }
22
+
23
+ [status, headers, [body]]
24
+ end
25
+
26
+ def call(env)
27
+ unless authenticate(env)
28
+ return rack_response(403, 'Invalid auth token', 'text/plain')
29
+ end
30
+
31
+ case env['PATH_INFO']
32
+ when /\/stop$/
33
+ @cli.stop
34
+ return rack_response(200, OK_STATUS)
35
+
36
+ when /\/halt$/
37
+ @cli.halt
38
+ return rack_response(200, OK_STATUS)
39
+
40
+ when /\/restart$/
41
+ @cli.restart
42
+ return rack_response(200, OK_STATUS)
43
+
44
+ when /\/phased-restart$/
45
+ if !@cli.phased_restart
46
+ return rack_response(404, '{ "error": "phased restart not available" }')
47
+ else
48
+ return rack_response(200, OK_STATUS)
49
+ end
50
+
51
+ when /\/reload-worker-directory$/
52
+ if !@cli.send(:reload_worker_directory)
53
+ return rack_response(404, '{ "error": "reload_worker_directory not available" }')
54
+ else
55
+ return rack_response(200, OK_STATUS)
56
+ end
57
+
58
+ when /\/stats$/
59
+ return rack_response(200, @cli.stats)
60
+ else
61
+ rack_response 404, "Unsupported action", 'text/plain'
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,402 @@
1
+ require 'uri'
2
+ require 'socket'
3
+
4
+ require 'puma/const'
5
+ require 'puma/util'
6
+
7
+ module Puma
8
+ class Binder
9
+ include Puma::Const
10
+
11
+ RACK_VERSION = [1,3].freeze
12
+
13
+ def initialize(events)
14
+ @events = events
15
+ @listeners = []
16
+ @inherited_fds = {}
17
+ @activated_sockets = {}
18
+ @unix_paths = []
19
+
20
+ @proto_env = {
21
+ "rack.version".freeze => RACK_VERSION,
22
+ "rack.errors".freeze => events.stderr,
23
+ "rack.multithread".freeze => true,
24
+ "rack.multiprocess".freeze => false,
25
+ "rack.run_once".freeze => false,
26
+ "SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "",
27
+
28
+ # I'd like to set a default CONTENT_TYPE here but some things
29
+ # depend on their not being a default set and inferring
30
+ # it from the content. And so if i set it here, it won't
31
+ # infer properly.
32
+
33
+ "QUERY_STRING".freeze => "",
34
+ SERVER_PROTOCOL => HTTP_11,
35
+ SERVER_SOFTWARE => PUMA_SERVER_STRING,
36
+ GATEWAY_INTERFACE => CGI_VER
37
+ }
38
+
39
+ @envs = {}
40
+ @ios = []
41
+ end
42
+
43
+ attr_reader :listeners, :ios
44
+
45
+ def env(sock)
46
+ @envs.fetch(sock, @proto_env)
47
+ end
48
+
49
+ def close
50
+ @ios.each { |i| i.close }
51
+ @unix_paths.each { |i| File.unlink i }
52
+ end
53
+
54
+ def import_from_env
55
+ remove = []
56
+
57
+ ENV.each do |k,v|
58
+ if k =~ /PUMA_INHERIT_\d+/
59
+ fd, url = v.split(":", 2)
60
+ @inherited_fds[url] = fd.to_i
61
+ remove << k
62
+ elsif k == 'LISTEN_FDS' && ENV['LISTEN_PID'].to_i == $$
63
+ v.to_i.times do |num|
64
+ fd = num + 3
65
+ sock = TCPServer.for_fd(fd)
66
+ begin
67
+ key = [ :unix, Socket.unpack_sockaddr_un(sock.getsockname) ]
68
+ rescue ArgumentError
69
+ port, addr = Socket.unpack_sockaddr_in(sock.getsockname)
70
+ if addr =~ /\:/
71
+ addr = "[#{addr}]"
72
+ end
73
+ key = [ :tcp, addr, port ]
74
+ end
75
+ @activated_sockets[key] = sock
76
+ @events.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
77
+ end
78
+ remove << k << 'LISTEN_PID'
79
+ end
80
+ end
81
+
82
+ remove.each do |k|
83
+ ENV.delete k
84
+ end
85
+ end
86
+
87
+ def parse(binds, logger)
88
+ binds.each do |str|
89
+ uri = URI.parse str
90
+ case uri.scheme
91
+ when "tcp"
92
+ if fd = @inherited_fds.delete(str)
93
+ logger.log "* Inherited #{str}"
94
+ io = inherit_tcp_listener uri.host, uri.port, fd
95
+ elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
96
+ logger.log "* Activated #{str}"
97
+ io = inherit_tcp_listener uri.host, uri.port, sock
98
+ else
99
+ params = Util.parse_query uri.query
100
+
101
+ opt = params.key?('low_latency')
102
+ bak = params.fetch('backlog', 1024).to_i
103
+
104
+ logger.log "* Listening on #{str}"
105
+ io = add_tcp_listener uri.host, uri.port, opt, bak
106
+ end
107
+
108
+ @listeners << [str, io] if io
109
+ when "unix"
110
+ path = "#{uri.host}#{uri.path}".gsub("%20", " ")
111
+
112
+ if fd = @inherited_fds.delete(str)
113
+ logger.log "* Inherited #{str}"
114
+ io = inherit_unix_listener path, fd
115
+ elsif sock = @activated_sockets.delete([ :unix, path ])
116
+ logger.log "* Activated #{str}"
117
+ io = inherit_unix_listener path, sock
118
+ else
119
+ logger.log "* Listening on #{str}"
120
+
121
+ umask = nil
122
+ mode = nil
123
+ backlog = nil
124
+
125
+ if uri.query
126
+ params = Util.parse_query uri.query
127
+ if u = params['umask']
128
+ # Use Integer() to respect the 0 prefix as octal
129
+ umask = Integer(u)
130
+ end
131
+
132
+ if u = params['mode']
133
+ mode = Integer('0'+u)
134
+ end
135
+
136
+ if u = params['backlog']
137
+ backlog = Integer(u)
138
+ end
139
+ end
140
+
141
+ io = add_unix_listener path, umask, mode, backlog
142
+ end
143
+
144
+ @listeners << [str, io]
145
+ when "ssl"
146
+ params = Util.parse_query uri.query
147
+ require 'puma/minissl'
148
+
149
+ MiniSSL.check
150
+
151
+ ctx = MiniSSL::Context.new
152
+
153
+ if defined?(JRUBY_VERSION)
154
+ unless params['keystore']
155
+ @events.error "Please specify the Java keystore via 'keystore='"
156
+ end
157
+
158
+ ctx.keystore = params['keystore']
159
+
160
+ unless params['keystore-pass']
161
+ @events.error "Please specify the Java keystore password via 'keystore-pass='"
162
+ end
163
+
164
+ ctx.keystore_pass = params['keystore-pass']
165
+ else
166
+ unless params['key']
167
+ @events.error "Please specify the SSL key via 'key='"
168
+ end
169
+
170
+ ctx.key = params['key']
171
+
172
+ unless params['cert']
173
+ @events.error "Please specify the SSL cert via 'cert='"
174
+ end
175
+
176
+ ctx.cert = params['cert']
177
+
178
+ if ['peer', 'force_peer'].include?(params['verify_mode'])
179
+ unless params['ca']
180
+ @events.error "Please specify the SSL ca via 'ca='"
181
+ end
182
+ end
183
+
184
+ ctx.ca = params['ca'] if params['ca']
185
+ end
186
+
187
+ if params['verify_mode']
188
+ ctx.verify_mode = case params['verify_mode']
189
+ when "peer"
190
+ MiniSSL::VERIFY_PEER
191
+ when "force_peer"
192
+ MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
193
+ when "none"
194
+ MiniSSL::VERIFY_NONE
195
+ else
196
+ @events.error "Please specify a valid verify_mode="
197
+ MiniSSL::VERIFY_NONE
198
+ end
199
+ end
200
+
201
+ if fd = @inherited_fds.delete(str)
202
+ logger.log "* Inherited #{str}"
203
+ io = inherit_ssl_listener fd, ctx
204
+ elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
205
+ logger.log "* Activated #{str}"
206
+ io = inherit_ssl_listener sock, ctx
207
+ else
208
+ logger.log "* Listening on #{str}"
209
+ io = add_ssl_listener uri.host, uri.port, ctx
210
+ end
211
+
212
+ @listeners << [str, io] if io
213
+ else
214
+ logger.error "Invalid URI: #{str}"
215
+ end
216
+ end
217
+
218
+ # If we inherited fds but didn't use them (because of a
219
+ # configuration change), then be sure to close them.
220
+ @inherited_fds.each do |str, fd|
221
+ logger.log "* Closing unused inherited connection: #{str}"
222
+
223
+ begin
224
+ IO.for_fd(fd).close
225
+ rescue SystemCallError
226
+ end
227
+
228
+ # We have to unlink a unix socket path that's not being used
229
+ uri = URI.parse str
230
+ if uri.scheme == "unix"
231
+ path = "#{uri.host}#{uri.path}"
232
+ File.unlink path
233
+ end
234
+ end
235
+
236
+ # Also close any unused activated sockets
237
+ @activated_sockets.each do |key, sock|
238
+ logger.log "* Closing unused activated socket: #{key.join ':'}"
239
+ begin
240
+ sock.close
241
+ rescue SystemCallError
242
+ end
243
+ # We have to unlink a unix socket path that's not being used
244
+ File.unlink key[1] if key[0] == :unix
245
+ end
246
+ end
247
+
248
+ def localhost_addresses
249
+ addrs = TCPSocket.gethostbyname "localhost"
250
+ addrs[3..-1].uniq
251
+ end
252
+
253
+ # Tell the server to listen on host +host+, port +port+.
254
+ # If +optimize_for_latency+ is true (the default) then clients connecting
255
+ # will be optimized for latency over throughput.
256
+ #
257
+ # +backlog+ indicates how many unaccepted connections the kernel should
258
+ # allow to accumulate before returning connection refused.
259
+ #
260
+ def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
261
+ if host == "localhost"
262
+ localhost_addresses.each do |addr|
263
+ add_tcp_listener addr, port, optimize_for_latency, backlog
264
+ end
265
+ return
266
+ end
267
+
268
+ host = host[1..-2] if host and host[0..0] == '['
269
+ s = TCPServer.new(host, port)
270
+ if optimize_for_latency
271
+ s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
272
+ end
273
+ s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
274
+ s.listen backlog
275
+ @connected_port = s.addr[1]
276
+
277
+ @ios << s
278
+ s
279
+ end
280
+
281
+ attr_reader :connected_port
282
+
283
+ def inherit_tcp_listener(host, port, fd)
284
+ if fd.kind_of? TCPServer
285
+ s = fd
286
+ else
287
+ s = TCPServer.for_fd(fd)
288
+ end
289
+
290
+ @ios << s
291
+ s
292
+ end
293
+
294
+ def add_ssl_listener(host, port, ctx,
295
+ optimize_for_latency=true, backlog=1024)
296
+ require 'puma/minissl'
297
+
298
+ MiniSSL.check
299
+
300
+ if host == "localhost"
301
+ localhost_addresses.each do |addr|
302
+ add_ssl_listener addr, port, ctx, optimize_for_latency, backlog
303
+ end
304
+ return
305
+ end
306
+
307
+ host = host[1..-2] if host[0..0] == '['
308
+ s = TCPServer.new(host, port)
309
+ if optimize_for_latency
310
+ s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
311
+ end
312
+ s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
313
+ s.listen backlog
314
+
315
+ ssl = MiniSSL::Server.new s, ctx
316
+ env = @proto_env.dup
317
+ env[HTTPS_KEY] = HTTPS
318
+ @envs[ssl] = env
319
+
320
+ @ios << ssl
321
+ s
322
+ end
323
+
324
+ def inherit_ssl_listener(fd, ctx)
325
+ require 'puma/minissl'
326
+ MiniSSL.check
327
+
328
+ if fd.kind_of? TCPServer
329
+ s = fd
330
+ else
331
+ s = TCPServer.for_fd(fd)
332
+ end
333
+ ssl = MiniSSL::Server.new(s, ctx)
334
+
335
+ env = @proto_env.dup
336
+ env[HTTPS_KEY] = HTTPS
337
+ @envs[ssl] = env
338
+
339
+ @ios << ssl
340
+
341
+ s
342
+ end
343
+
344
+ # Tell the server to listen on +path+ as a UNIX domain socket.
345
+ #
346
+ def add_unix_listener(path, umask=nil, mode=nil, backlog=nil)
347
+ @unix_paths << path
348
+
349
+ # Let anyone connect by default
350
+ umask ||= 0
351
+
352
+ begin
353
+ old_mask = File.umask(umask)
354
+
355
+ if File.exist? path
356
+ begin
357
+ old = UNIXSocket.new path
358
+ rescue SystemCallError, IOError
359
+ File.unlink path
360
+ else
361
+ old.close
362
+ raise "There is already a server bound to: #{path}"
363
+ end
364
+ end
365
+
366
+ s = UNIXServer.new(path)
367
+ s.listen backlog if backlog
368
+ @ios << s
369
+ ensure
370
+ File.umask old_mask
371
+ end
372
+
373
+ if mode
374
+ File.chmod mode, path
375
+ end
376
+
377
+ env = @proto_env.dup
378
+ env[REMOTE_ADDR] = "127.0.0.1"
379
+ @envs[s] = env
380
+
381
+ s
382
+ end
383
+
384
+ def inherit_unix_listener(path, fd)
385
+ @unix_paths << path
386
+
387
+ if fd.kind_of? TCPServer
388
+ s = fd
389
+ else
390
+ s = UNIXServer.for_fd fd
391
+ end
392
+ @ios << s
393
+
394
+ env = @proto_env.dup
395
+ env[REMOTE_ADDR] = "127.0.0.1"
396
+ @envs[s] = env
397
+
398
+ s
399
+ end
400
+
401
+ end
402
+ end