unicorn 4.6.3 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- DEF_VER = "v4.6.3"
2
+ DEF_VER = "v4.7.0"
3
3
  CONSTANT = "Unicorn::Const::UNICORN_VERSION"
4
4
  RVF = "lib/unicorn/version.rb"
5
5
  GVF = "GIT-VERSION-FILE"
@@ -256,7 +256,6 @@ release: verify package $(release_notes) $(release_changes)
256
256
  # in case of gem downloads from RubyForge releases page
257
257
  -rubyforge add_file \
258
258
  $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
259
- $(RAKE) raa_update VERSION=$(VERSION)
260
259
  $(RAKE) fm_update VERSION=$(VERSION)
261
260
  else
262
261
  gem install-gem: GIT-VERSION-FILE
data/LICENSE CHANGED
@@ -3,15 +3,18 @@ revision control for names and email addresses of all of them.
3
3
 
4
4
  You can redistribute it and/or modify it under either the terms of the
5
5
  GNU General Public License (GPL) as published by the Free Software
6
- Foundation (FSF), version {3.0}[http://www.gnu.org/licenses/gpl-3.0.txt]
7
- or version {2.0}[http://www.gnu.org/licenses/gpl-2.0.txt]
8
- or the Ruby-specific license terms (see below).
6
+ Foundation (FSF), either version 2 of the License, or (at your option)
7
+ any later version. We currently prefer the GPLv3 or later for
8
+ derivative works, but the GPLv2 is fine.
9
9
 
10
- The unicorn project leader (Eric Wong) reserves the right to add future
11
- versions of the GPL (and no other licenses) as published by the FSF to
12
- the licensing terms.
10
+ The complete texts of the GPLv2 and GPLv3 are below:
11
+ GPLv2 - http://www.gnu.org/licenses/gpl-2.0.txt
12
+ GPLv3 - http://www.gnu.org/licenses/gpl-3.0.txt
13
13
 
14
- === Ruby-specific terms (if you're not using the GPLv2 or GPLv3)
14
+ You may (against our _preference_) also use the Ruby 1.8 license terms
15
+ which we inherited from the original Mongrel project when we forked it:
16
+
17
+ === Ruby 1.8-specific terms (if you're not using the GPL)
15
18
 
16
19
  1. You may make and give away verbatim copies of the source form of the
17
20
  software without restriction, provided that you duplicate all of the
data/README CHANGED
@@ -63,8 +63,9 @@ both the the request and response in between \Unicorn and slow clients.
63
63
  It is based on Mongrel 1.1.5.
64
64
  Mongrel is copyright 2007 Zed A. Shaw and contributors.
65
65
 
66
- \Unicorn is tri-licensed under (your choice) of the GPLv3, GPLv2 or
67
- Ruby (1.8)-specific terms. See the included LICENSE file for details.
66
+ \Unicorn is licensed under (your choice) of the GPLv2 or later
67
+ (GPLv3+ preferred), or Ruby (1.8)-specific terms.
68
+ See the included LICENSE file for details.
68
69
 
69
70
  \Unicorn is 100% Free Software.
70
71
 
data/Rakefile CHANGED
@@ -5,43 +5,6 @@ require 'wrongdoc'
5
5
  cgit_url = Wrongdoc.config[:cgit_url]
6
6
  git_url = Wrongdoc.config[:git_url]
7
7
 
8
- desc "post to RAA"
9
- task :raa_update do
10
- require 'net/http'
11
- require 'net/netrc'
12
- rc = Net::Netrc.locate('unicorn-raa') or abort "~/.netrc not found"
13
- password = rc.password
14
-
15
- s = Gem::Specification.load('unicorn.gemspec')
16
- desc = [ s.description.strip ]
17
- desc << ""
18
- desc << "* #{s.email}"
19
- desc << "* #{git_url}"
20
- desc << "* #{cgit_url}"
21
- desc = desc.join("\n")
22
- uri = URI.parse('http://raa.ruby-lang.org/regist.rhtml')
23
- form = {
24
- :name => s.name,
25
- :short_description => s.summary,
26
- :version => s.version.to_s,
27
- :status => 'stable',
28
- :owner => s.authors.first,
29
- :email => s.email,
30
- :category_major => 'Library',
31
- :category_minor => 'Web',
32
- :url => s.homepage,
33
- :download => "http://rubyforge.org/frs/?group_id=1306",
34
- :license => "Ruby's",
35
- :description_style => 'Plain',
36
- :description => desc,
37
- :pass => password,
38
- :submit => "Update",
39
- }
40
- res = Net::HTTP.post_form(uri, form)
41
- p res
42
- puts res.body
43
- end
44
-
45
8
  desc "post to FM"
46
9
  task :fm_update do
47
10
  require 'tempfile'
data/Sandbox CHANGED
@@ -60,6 +60,13 @@ If you're using an older Bundler version (0.9.x), you may need to set or
60
60
  reset GEM_HOME, GEM_PATH and PATH environment variables in the
61
61
  before_exec hook as illustrated by http://gist.github.com/534668
62
62
 
63
+ === Ruby 2.0.0 close-on-exec and SIGUSR2 incompatibility
64
+
65
+ Ruby 2.0.0 enforces FD_CLOEXEC on file descriptors by default. unicorn
66
+ has been prepared for this behavior since unicorn 4.1.0, but we forgot
67
+ to remind the Bundler developers. This issue is being tracked here:
68
+ https://github.com/bundler/bundler/issues/2628
69
+
63
70
  == Isolate
64
71
 
65
72
  === Running
@@ -47,9 +47,9 @@ op = OptionParser.new("", 24, ' ') do |opts|
47
47
  rackup_opts[:set_listener] = true
48
48
  end
49
49
 
50
- opts.on("-p", "--port PORT",
51
- "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |p|
52
- rackup_opts[:port] = p.to_i
50
+ opts.on("-p", "--port PORT", Integer,
51
+ "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |port|
52
+ rackup_opts[:port] = port
53
53
  rackup_opts[:set_listener] = true
54
54
  end
55
55
 
@@ -48,9 +48,9 @@ op = OptionParser.new("", 24, ' ') do |opts|
48
48
  rackup_opts[:set_listener] = true
49
49
  end
50
50
 
51
- opts.on("-p", "--port PORT",
52
- "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |p|
53
- rackup_opts[:port] = p.to_i
51
+ opts.on("-p", "--port PORT", Integer,
52
+ "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |port|
53
+ rackup_opts[:port] = port
54
54
  rackup_opts[:set_listener] = true
55
55
  end
56
56
 
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) 2009 Eric Wong (all bugs are Eric's fault)
3
3
  * Copyright (c) 2005 Zed A. Shaw
4
4
  * You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- * the GPLv3
5
+ * the GPLv2+ (GPLv3+ preferred)
6
6
  */
7
7
  #include "ruby.h"
8
8
  #include "ext_help.h"
@@ -2,7 +2,7 @@
2
2
  # :enddoc:
3
3
  # Copyright (c) 2009 Eric Wong
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- # the GPLv3
5
+ # the GPLv2+ (GPLv3+ preferred)
6
6
 
7
7
  # this class *must* be used with Rack::Chunked
8
8
  module Unicorn::App
@@ -5,7 +5,7 @@
5
5
  # Copyright (c) 2005 Zed A. Shaw
6
6
  # Copyright (c) 2009 Eric Wong
7
7
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
8
- # the GPLv3
8
+ # the GPLv2+ (GPLv3+ preferred)
9
9
  # Additional work donated by contributors. See CONTRIBUTORS for more info.
10
10
  require 'unicorn/cgi_wrapper'
11
11
  require 'dispatcher'
@@ -5,7 +5,7 @@
5
5
  # Copyright (c) 2005 Zed A. Shaw
6
6
  # Copyright (c) 2009 Eric Wong
7
7
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
8
- # the GPLv3
8
+ # the GPLv2+ (GPLv3+ preferred)
9
9
  #
10
10
  # Additional work donated by contributors. See CONTRIBUTORS for more info.
11
11
 
@@ -319,6 +319,25 @@ class Unicorn::Configurator
319
319
  #
320
320
  # Default: Operating-system dependent
321
321
  #
322
+ # [:reuseport => true or false]
323
+ #
324
+ # This enables multiple, independently-started unicorn instances to
325
+ # bind to the same port (as long as all the processes enable this).
326
+ #
327
+ # This option must be used when unicorn first binds the listen socket.
328
+ # It cannot be enabled when a socket is inherited via SIGUSR2
329
+ # (but it will remain on if inherited), and it cannot be enabled
330
+ # directly via SIGHUP.
331
+ #
332
+ # Note: there is a chance of connections being dropped if
333
+ # one of the unicorn instances is stopped while using this.
334
+ #
335
+ # This is supported on *BSD systems and Linux 3.9 or later.
336
+ #
337
+ # ref: https://lwn.net/Articles/542629/
338
+ #
339
+ # Default: false (unset)
340
+ #
322
341
  # [:tries => Integer]
323
342
  #
324
343
  # Times to retry binding a socket if it is already in use
@@ -396,7 +415,7 @@ class Unicorn::Configurator
396
415
  Integer === value or
397
416
  raise ArgumentError, "not an integer: #{key}=#{value.inspect}"
398
417
  end
399
- [ :tcp_nodelay, :tcp_nopush, :ipv6only ].each do |key|
418
+ [ :tcp_nodelay, :tcp_nopush, :ipv6only, :reuseport ].each do |key|
400
419
  (value = options[key]).nil? and next
401
420
  TrueClass === value || FalseClass === value or
402
421
  raise ArgumentError, "not boolean: #{key}=#{value.inspect}"
@@ -134,11 +134,22 @@ class Unicorn::HttpServer
134
134
  # Note that signals don't actually get handled until the #join method
135
135
  QUEUE_SIGS.each { |sig| trap(sig) { SIG_QUEUE << sig; awaken_master } }
136
136
  trap(:CHLD) { awaken_master }
137
- self.pid = config[:pid]
137
+
138
+ # write pid early for Mongrel compatibility if we're not inheriting sockets
139
+ # This was needed for compatibility with some health checker a long time
140
+ # ago. This unfortunately has the side effect of clobbering valid PID
141
+ # files.
142
+ self.pid = config[:pid] unless ENV["UNICORN_FD"]
138
143
 
139
144
  self.master_pid = $$
140
145
  build_app! if preload_app
141
146
  bind_new_listeners!
147
+
148
+ # Assuming preload_app==false, we drop the pid file after the app is ready
149
+ # to process requests. If binding or build_app! fails with
150
+ # preload_app==true, we'll never get here and the parent will recover
151
+ self.pid = config[:pid] if ENV["UNICORN_FD"]
152
+
142
153
  spawn_missing_workers
143
154
  self
144
155
  end
@@ -180,6 +191,21 @@ class Unicorn::HttpServer
180
191
  Unicorn::HttpRequest::DEFAULTS["rack.logger"] = @logger = obj
181
192
  end
182
193
 
194
+ def clobber_pid(path)
195
+ unlink_pid_safe(@pid) if @pid
196
+ if path
197
+ fp = begin
198
+ tmp = "#{File.dirname(path)}/#{rand}.#$$"
199
+ File.open(tmp, File::RDWR|File::CREAT|File::EXCL, 0644)
200
+ rescue Errno::EEXIST
201
+ retry
202
+ end
203
+ fp.syswrite("#$$\n")
204
+ File.rename(fp.path, path)
205
+ fp.close
206
+ end
207
+ end
208
+
183
209
  # sets the path for the PID file of the master process
184
210
  def pid=(path)
185
211
  if path
@@ -194,18 +220,18 @@ class Unicorn::HttpServer
194
220
  "(or pid=#{path} is stale)"
195
221
  end
196
222
  end
197
- unlink_pid_safe(pid) if pid
198
223
 
199
- if path
200
- fp = begin
201
- tmp = "#{File.dirname(path)}/#{rand}.#$$"
202
- File.open(tmp, File::RDWR|File::CREAT|File::EXCL, 0644)
203
- rescue Errno::EEXIST
204
- retry
224
+ # rename the old pid if possible
225
+ if @pid && path
226
+ begin
227
+ File.rename(@pid, path)
228
+ rescue Errno::ENOENT, Errno::EXDEV
229
+ # a user may have accidentally removed the original,
230
+ # obviously cross-FS renames don't work, either.
231
+ clobber_pid(path)
205
232
  end
206
- fp.syswrite("#$$\n")
207
- File.rename(fp.path, path)
208
- fp.close
233
+ else
234
+ clobber_pid(path)
209
235
  end
210
236
  @pid = path
211
237
  end
@@ -228,7 +254,7 @@ class Unicorn::HttpServer
228
254
  begin
229
255
  io = bind_listen(address, opt)
230
256
  unless Kgio::TCPServer === io || Kgio::UNIXServer === io
231
- IO_PURGATORY << io
257
+ prevent_autoclose(io)
232
258
  io = server_cast(io)
233
259
  end
234
260
  logger.info "listening on addr=#{sock_name(io)} fd=#{io.fileno}"
@@ -423,13 +449,14 @@ class Unicorn::HttpServer
423
449
  end
424
450
 
425
451
  self.reexec_pid = fork do
426
- listener_fds = Hash[LISTENERS.map do |sock|
452
+ listener_fds = {}
453
+ LISTENERS.each do |sock|
427
454
  # IO#close_on_exec= will be available on any future version of
428
455
  # Ruby that sets FD_CLOEXEC by default on new file descriptors
429
456
  # ref: http://redmine.ruby-lang.org/issues/5041
430
457
  sock.close_on_exec = false if sock.respond_to?(:close_on_exec=)
431
- [ sock.fileno, sock ]
432
- end]
458
+ listener_fds[sock.fileno] = sock
459
+ end
433
460
  ENV['UNICORN_FD'] = listener_fds.keys.join(',')
434
461
  Dir.chdir(START_CTX[:cwd])
435
462
  cmd = [ START_CTX[0] ].concat(START_CTX[:argv])
@@ -440,7 +467,7 @@ class Unicorn::HttpServer
440
467
  (3..1024).each do |io|
441
468
  next if listener_fds.include?(io)
442
469
  io = IO.for_fd(io) rescue next
443
- IO_PURGATORY << io
470
+ prevent_autoclose(io)
444
471
  io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
445
472
  end
446
473
 
@@ -520,9 +547,8 @@ class Unicorn::HttpServer
520
547
  # the socket is closed at the end of this function
521
548
  def handle_error(client, e)
522
549
  code = case e
523
- when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF,
524
- Errno::ENOTCONN
525
- 500
550
+ when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::ENOTCONN
551
+ # client disconnected on us and there's nothing we can do
526
552
  when Unicorn::RequestURITooLongError
527
553
  414
528
554
  when Unicorn::RequestEntityTooLargeError
@@ -533,7 +559,9 @@ class Unicorn::HttpServer
533
559
  Unicorn.log_error(@logger, "app error", e)
534
560
  500
535
561
  end
536
- client.kgio_trywrite(err_response(code, @request.response_start_sent))
562
+ if code
563
+ client.kgio_trywrite(err_response(code, @request.response_start_sent))
564
+ end
537
565
  client.close
538
566
  rescue
539
567
  end
@@ -745,7 +773,7 @@ class Unicorn::HttpServer
745
773
  inherited = ENV['UNICORN_FD'].to_s.split(/,/).map do |fd|
746
774
  io = Socket.for_fd(fd.to_i)
747
775
  set_server_sockopt(io, listener_opts[sock_name(io)])
748
- IO_PURGATORY << io
776
+ prevent_autoclose(io)
749
777
  logger.info "inherited addr=#{sock_name(io)} fd=#{fd}"
750
778
  server_cast(io)
751
779
  end
@@ -8,6 +8,7 @@ module Unicorn
8
8
  include Socket::Constants
9
9
 
10
10
  # prevents IO objects in here from being GC-ed
11
+ # kill this when we drop 1.8 support
11
12
  IO_PURGATORY = []
12
13
 
13
14
  # internal interface, only used by Rainbows!/Zbatery
@@ -41,6 +42,15 @@ module Unicorn
41
42
 
42
43
  # do not send out partial frames (Linux)
43
44
  TCP_CORK = 3 unless defined?(TCP_CORK)
45
+
46
+ # Linux got SO_REUSEPORT in 3.9, BSDs have had it for ages
47
+ unless defined?(SO_REUSEPORT)
48
+ if RUBY_PLATFORM =~ /(?:alpha|mips|parisc|sparc)/
49
+ SO_REUSEPORT = 0x0200 # untested
50
+ else
51
+ SO_REUSEPORT = 15 # only tested on x86_64 and i686
52
+ end
53
+ end
44
54
  when /freebsd/
45
55
  # do not send out partial frames (FreeBSD)
46
56
  TCP_NOPUSH = 4 unless defined?(TCP_NOPUSH)
@@ -50,6 +60,14 @@ module Unicorn
50
60
  end if defined?(SO_ACCEPTFILTER)
51
61
  end
52
62
 
63
+ def prevent_autoclose(io)
64
+ if io.respond_to?(:autoclose=)
65
+ io.autoclose = false
66
+ else
67
+ IO_PURGATORY << io
68
+ end
69
+ end
70
+
53
71
  def set_tcp_sockopt(sock, opt)
54
72
  # just in case, even LANs can break sometimes. Linux sysadmins
55
73
  # can lower net.ipv4.tcp_keepalive_* sysctl knobs to very low values.
@@ -142,9 +160,9 @@ module Unicorn
142
160
  File.umask(old_umask)
143
161
  end
144
162
  elsif /\A\[([a-fA-F0-9:]+)\]:(\d+)\z/ =~ address
145
- new_ipv6_server($1, $2.to_i, opt)
163
+ new_tcp_server($1, $2.to_i, opt.merge(:ipv6=>true))
146
164
  elsif /\A(\d+\.\d+\.\d+\.\d+):(\d+)\z/ =~ address
147
- Kgio::TCPServer.new($1, $2.to_i)
165
+ new_tcp_server($1, $2.to_i, opt)
148
166
  else
149
167
  raise ArgumentError, "Don't know how to bind: #{address}"
150
168
  end
@@ -152,15 +170,20 @@ module Unicorn
152
170
  sock
153
171
  end
154
172
 
155
- def new_ipv6_server(addr, port, opt)
156
- opt.key?(:ipv6only) or return Kgio::TCPServer.new(addr, port)
157
- defined?(IPV6_V6ONLY) or
158
- abort "Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS"
159
- sock = Socket.new(AF_INET6, SOCK_STREAM, 0)
160
- sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0)
173
+ def new_tcp_server(addr, port, opt)
174
+ # n.b. we set FD_CLOEXEC in the workers
175
+ sock = Socket.new(opt[:ipv6] ? AF_INET6 : AF_INET, SOCK_STREAM, 0)
176
+ if opt.key?(:ipv6only)
177
+ defined?(IPV6_V6ONLY) or
178
+ abort "Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS"
179
+ sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0)
180
+ end
161
181
  sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
182
+ if defined?(SO_REUSEPORT) && opt[:reuseport]
183
+ sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
184
+ end
162
185
  sock.bind(Socket.pack_sockaddr_in(port, addr))
163
- IO_PURGATORY << sock
186
+ prevent_autoclose(sock)
164
187
  Kgio::TCPServer.for_fd(sock.fileno)
165
188
  end
166
189
 
@@ -39,7 +39,7 @@ module Unicorn::Util
39
39
  to_reopen.each do |fp|
40
40
  orig_st = begin
41
41
  fp.stat
42
- rescue IOError, Errno::EBADF
42
+ rescue IOError, Errno::EBADF # race
43
43
  next
44
44
  end
45
45
 
@@ -50,8 +50,28 @@ module Unicorn::Util
50
50
  end
51
51
 
52
52
  begin
53
- File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) }
53
+ # stdin, stdout, stderr are special. The following dance should
54
+ # guarantee there is no window where `fp' is unwritable in MRI
55
+ # (or any correct Ruby implementation).
56
+ #
57
+ # Fwiw, GVL has zero bearing here. This is tricky because of
58
+ # the unavoidable existence of stdio FILE * pointers for
59
+ # std{in,out,err} in all programs which may use the standard C library
60
+ if fp.fileno <= 2
61
+ # We do not want to hit fclose(3)->dup(2) window for std{in,out,err}
62
+ # MRI will use freopen(3) here internally on std{in,out,err}
63
+ fp.reopen(fp.path, "a")
64
+ else
65
+ # We should not need this workaround, Ruby can be fixed:
66
+ # http://bugs.ruby-lang.org/issues/9036
67
+ # MRI will not call call fclose(3) or freopen(3) here
68
+ # since there's no associated std{in,out,err} FILE * pointer
69
+ # This should atomically use dup3(2) (or dup2(2)) syscall
70
+ File.open(fp.path, "a") { |tmpfp| fp.reopen(tmpfp) }
71
+ end
72
+
54
73
  fp.sync = true
74
+ fp.flush # IO#sync=true may not implicitly flush
55
75
  new_st = fp.stat
56
76
 
57
77
  # this should only happen in the master:
@@ -16,10 +16,10 @@ opts = {
16
16
 
17
17
  pid = fork do
18
18
  Isolate.now!(opts) do
19
- gem 'raindrops', '0.10.0'
19
+ gem 'raindrops', '0.12.0'
20
20
  gem 'kgio-monkey', '0.4.0'
21
- gem 'kgio', '2.8.0'
22
- gem 'rack', '1.5.1'
21
+ gem 'kgio', '2.8.1'
22
+ gem 'rack', '1.5.2'
23
23
  end
24
24
  end
25
25
  _, status = Process.waitpid2(pid)
@@ -7,8 +7,7 @@ $gc_started = false
7
7
 
8
8
  # Mock GC.start
9
9
  def GC.start
10
- ObjectSpace.each_object(BasicSocket) do |x|
11
- next if Unicorn::HttpServer::LISTENERS.include?(x)
10
+ ObjectSpace.each_object(Kgio::Socket) do |x|
12
11
  x.closed? or abort "not closed #{x}"
13
12
  end
14
13
  $gc_started = true
@@ -7,8 +7,7 @@ $gc_started = false
7
7
 
8
8
  # Mock GC.start
9
9
  def GC.start
10
- ObjectSpace.each_object(BasicSocket) do |x|
11
- next if Unicorn::HttpServer::LISTENERS.include?(x)
10
+ ObjectSpace.each_object(Kgio::Socket) do |x|
12
11
  x.closed? or abort "not closed #{x}"
13
12
  end
14
13
  $gc_started = true
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2005 Zed A. Shaw
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- # the GPLv3
5
+ # the GPLv2+ (GPLv3+ preferred)
6
6
  #
7
7
  # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
8
8
  # for more information.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2005 Zed A. Shaw
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- # the GPLv3
5
+ # the GPLv2+ (GPLv3+ preferred)
6
6
  #
7
7
  # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
8
8
  # for more information.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2009 Eric Wong
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- # the GPLv3
5
+ # the GPLv2+ (GPLv3+ preferred)
6
6
 
7
7
  require 'test/test_helper'
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2005 Zed A. Shaw
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- # the GPLv3
5
+ # the GPLv2+ (GPLv3+ preferred)
6
6
  #
7
7
  # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
8
8
  # for more information.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2005 Zed A. Shaw
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- # the GPLv3
5
+ # the GPLv2+ (GPLv3+ preferred)
6
6
  #
7
7
  # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
8
8
  # for more information.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2009 Eric Wong
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
- # the GPLv3
5
+ # the GPLv2+ (GPLv3+ preferred)
6
6
  #
7
7
  # Ensure we stay sane in the face of signals being sent to us
8
8
 
@@ -184,4 +184,12 @@ class TestSocketHelper < Test::Unit::TestCase
184
184
  assert_equal 1, cur
185
185
  rescue Errno::EAFNOSUPPORT
186
186
  end if RUBY_VERSION >= "1.9.2"
187
+
188
+ def test_reuseport
189
+ port = unused_port @test_addr
190
+ name = "#@test_addr:#{port}"
191
+ sock = bind_listen(name, :reuseport => true)
192
+ cur = sock.getsockopt(Socket::SOL_SOCKET, SO_REUSEPORT).unpack('i')[0]
193
+ assert_equal 1, cur
194
+ end if defined?(SO_REUSEPORT)
187
195
  end
@@ -80,7 +80,11 @@ class TestUtil < Test::Unit::TestCase
80
80
  File.open(tmp_path, "a:#{ext.to_s}:#{int.to_s}") { |fp|
81
81
  fp.sync = true
82
82
  assert_equal ext, fp.external_encoding
83
- assert_equal int, fp.internal_encoding
83
+
84
+ if ext != Encoding::BINARY
85
+ assert_equal int, fp.internal_encoding
86
+ end
87
+
84
88
  File.unlink(tmp_path)
85
89
  assert ! File.exist?(tmp_path)
86
90
  Unicorn::Util.reopen_logs
@@ -88,7 +92,9 @@ class TestUtil < Test::Unit::TestCase
88
92
  assert File.exist?(tmp_path)
89
93
  assert_equal fp.stat.inspect, File.stat(tmp_path).inspect
90
94
  assert_equal ext, fp.external_encoding
91
- assert_equal int, fp.internal_encoding
95
+ if ext != Encoding::BINARY
96
+ assert_equal int, fp.internal_encoding
97
+ end
92
98
  assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & fp.fcntl(Fcntl::F_GETFL))
93
99
  assert fp.sync
94
100
  }
@@ -40,5 +40,5 @@ Gem::Specification.new do |s|
40
40
  s.add_development_dependency('isolate', '~> 3.2')
41
41
  s.add_development_dependency('wrongdoc', '~> 1.6.1')
42
42
 
43
- s.licenses = ["GPLv2", "GPLv3", "Ruby 1.8"]
43
+ s.licenses = ["GPLv2+", "Ruby 1.8"]
44
44
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: !binary |-
3
3
  dW5pY29ybg==
4
4
  version: !ruby/object:Gem::Version
5
- version: 4.6.3
5
+ version: 4.7.0
6
6
  prerelease:
7
7
  platform: ruby
8
8
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-06-21 00:00:00.000000000 Z
13
+ date: 2013-11-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: !binary |-
@@ -331,9 +331,7 @@ files:
331
331
  homepage: http://unicorn.bogomips.org/
332
332
  licenses:
333
333
  - !binary |-
334
- R1BMdjI=
335
- - !binary |-
336
- R1BMdjM=
334
+ R1BMdjIr
337
335
  - !binary |-
338
336
  UnVieSAxLjg=
339
337
  post_install_message: