diff options
-rw-r--r-- | .olddoc.yml | 1 | ||||
-rw-r--r-- | ISSUES | 18 | ||||
-rw-r--r-- | Links | 2 | ||||
-rw-r--r-- | ext/unicorn_http/common_field_optimization.h | 4 | ||||
-rw-r--r-- | ext/unicorn_http/global_variables.h | 4 | ||||
-rw-r--r-- | ext/unicorn_http/httpdate.c | 4 | ||||
-rw-r--r-- | ext/unicorn_http/unicorn_http.rl | 13 | ||||
-rw-r--r-- | lib/unicorn.rb | 2 | ||||
-rw-r--r-- | lib/unicorn/configurator.rb | 35 | ||||
-rw-r--r-- | lib/unicorn/http_server.rb | 5 | ||||
-rw-r--r-- | lib/unicorn/oob_gc.rb | 3 | ||||
-rw-r--r-- | lib/unicorn/socket_helper.rb | 7 | ||||
-rw-r--r-- | lib/unicorn/stream_input.rb | 9 | ||||
-rw-r--r-- | lib/unicorn/tee_input.rb | 14 | ||||
-rw-r--r-- | lib/unicorn/worker.rb | 13 | ||||
-rw-r--r-- | t/test-lib.sh | 4 | ||||
-rw-r--r-- | test/exec/test_exec.rb | 9 | ||||
-rw-r--r-- | test/unit/test_http_parser.rb | 18 | ||||
-rw-r--r-- | test/unit/test_socket_helper.rb | 12 | ||||
-rw-r--r-- | test/unit/test_util.rb | 4 |
20 files changed, 105 insertions, 76 deletions
diff --git a/.olddoc.yml b/.olddoc.yml index ee2d306..cacc0ab 100644 --- a/.olddoc.yml +++ b/.olddoc.yml @@ -12,7 +12,6 @@ noindex: - TODO - unicorn_rails_1 public_email: unicorn-public@bogomips.org -private_email: unicorn@bogomips.org nntp_url: - nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn - nntp://news.gmane.org/gmane.comp.lang.ruby.unicorn.general @@ -9,14 +9,16 @@ submit patches and/or obtain support after you have searched the * Cc: all participants in a thread or commit, as subscription is optional * Do not {top post}[http://catb.org/jargon/html/T/top-post.html] in replies * Quote as little as possible of the message you're replying to -* Do not send HTML mail or images, it will be flagged as spam -* Anonymous and pseudonymous messages will always be welcome. +* Do not send HTML mail or images, + they hurt reader privacy and will be flagged as spam +* Anonymous and pseudonymous messages will ALWAYS be welcome * The email submission port (587) is enabled on the bogomips.org MX: https://bogomips.org/unicorn-public/20141004232241.GA23908@dcvr.yhbt.net/t/ If your issue is of a sensitive nature or you're just shy in public, -then feel free to email us privately at mailto:unicorn@bogomips.org -instead and your issue will be handled discreetly. +use anonymity tools such as Tor or Mixmaster; and rely on the public +mail archives for responses. Be sure to scrub sensitive log messages +and such. If you don't get a response within a few days, we may have forgotten about it so feel free to ask again. @@ -64,14 +66,14 @@ document distributed with git) on guidelines for patch submission. == Contact Info * public: mailto:unicorn-public@bogomips.org -* private: mailto:unicorn@bogomips.org * nntp://news.gmane.org/gmane.comp.lang.ruby.unicorn.general * nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn * https://bogomips.org/unicorn-public/ +* http://ou63pmih66umazou.onion/unicorn-public/ Mailing list subscription is optional, so Cc: all participants. -You can follow along via NNTP: +You can follow along via NNTP (read-only): nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn nntp://news.gmane.org/gmane.comp.lang.ruby.unicorn.general @@ -79,6 +81,7 @@ You can follow along via NNTP: Or Atom feeds: https://bogomips.org/unicorn-public/new.atom + http://ou63pmih66umazou.onion/unicorn-public/new.atom The HTML archives at https://bogomips.org/unicorn-public/ also has links to per-thread Atom feeds and downloadable @@ -88,3 +91,6 @@ You may optionally subscribe via plain-text email: mailto:unicorn-public+subscribe@bogomips.org (and confirming the auto-reply) + +Just keep in mind we suck at delivering email, so using NNTP, +or Atom feeds might be a better bet... @@ -23,7 +23,7 @@ or services behind them. * {golden_brindle}[https://github.com/simonoff/golden_brindle] - tool to manage multiple unicorn instances/applications on a single server -* {raindrops}[http://raindrops.bogomips.org/] - real-time stats for +* {raindrops}[https://bogomips.org/raindrops/] - real-time stats for preforking Rack servers * {UnXF}[https://bogomips.org/unxf/] Un-X-Forward* the Rack environment, diff --git a/ext/unicorn_http/common_field_optimization.h b/ext/unicorn_http/common_field_optimization.h index 42c5430..251e734 100644 --- a/ext/unicorn_http/common_field_optimization.h +++ b/ext/unicorn_http/common_field_optimization.h @@ -60,7 +60,7 @@ static struct common_field common_http_fields[] = { #define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1) /* this function is not performance-critical, called only at load time */ -static void init_common_fields(void) +static void init_common_fields(VALUE mark_ary) { int i; struct common_field *cf = common_http_fields; @@ -77,7 +77,7 @@ static void init_common_fields(void) cf->value = rb_str_new(tmp, HTTP_PREFIX_LEN + cf->len); } cf->value = rb_obj_freeze(cf->value); - rb_global_variable(&cf->value); + rb_ary_push(mark_ary, cf->value); } } diff --git a/ext/unicorn_http/global_variables.h b/ext/unicorn_http/global_variables.h index e1c43c9..c17ee6a 100644 --- a/ext/unicorn_http/global_variables.h +++ b/ext/unicorn_http/global_variables.h @@ -56,7 +56,7 @@ NORETURN(static void parser_raise(VALUE klass, const char *)); /** Defines global strings in the init method. */ #define DEF_GLOBAL(N, val) do { \ g_##N = rb_obj_freeze(rb_str_new(val, sizeof(val) - 1)); \ - rb_global_variable(&g_##N); \ + rb_ary_push(mark_ary, g_##N); \ } while (0) /* Defines the maximum allowed lengths for various input elements.*/ @@ -67,7 +67,7 @@ DEF_MAX_LENGTH(FRAGMENT, 1024); /* Don't know if this length is specified somewh DEF_MAX_LENGTH(REQUEST_PATH, 4096); /* common PATH_MAX on modern systems */ DEF_MAX_LENGTH(QUERY_STRING, (1024 * 10)); -static void init_globals(void) +static void init_globals(VALUE mark_ary) { DEF_GLOBAL(rack_url_scheme, "rack.url_scheme"); DEF_GLOBAL(request_method, "REQUEST_METHOD"); diff --git a/ext/unicorn_http/httpdate.c b/ext/unicorn_http/httpdate.c index 0a1045f..2381cff 100644 --- a/ext/unicorn_http/httpdate.c +++ b/ext/unicorn_http/httpdate.c @@ -64,13 +64,13 @@ static VALUE httpdate(VALUE self) return buf; } -void init_unicorn_httpdate(void) +void init_unicorn_httpdate(VALUE mark_ary) { VALUE mod = rb_define_module("Unicorn"); mod = rb_define_module_under(mod, "HttpResponse"); buf = rb_str_new(0, buf_capa - 1); - rb_global_variable(&buf); + rb_ary_push(mark_ary, buf); buf_ptr = RSTRING_PTR(buf); httpdate(Qnil); diff --git a/ext/unicorn_http/unicorn_http.rl b/ext/unicorn_http/unicorn_http.rl index 957a5e3..6fc3498 100644 --- a/ext/unicorn_http/unicorn_http.rl +++ b/ext/unicorn_http/unicorn_http.rl @@ -13,7 +13,7 @@ #include "global_variables.h" #include "c_util.h" -void init_unicorn_httpdate(void); +void init_unicorn_httpdate(VALUE mark_ary); #define UH_FL_CHUNKED 0x1 #define UH_FL_HASBODY 0x2 @@ -917,8 +917,10 @@ static VALUE HttpParser_rssget(VALUE self) void Init_unicorn_http(void) { + static VALUE mark_ary; VALUE mUnicorn, cHttpParser; + mark_ary = rb_ary_new(); mUnicorn = rb_define_module("Unicorn"); cHttpParser = rb_define_class_under(mUnicorn, "HttpParser", rb_cObject); eHttpParserError = @@ -928,7 +930,7 @@ void Init_unicorn_http(void) e414 = rb_define_class_under(mUnicorn, "RequestURITooLongError", eHttpParserError); - init_globals(); + init_globals(mark_ary); rb_define_alloc_func(cHttpParser, HttpParser_alloc); rb_define_method(cHttpParser, "initialize", HttpParser_init, 0); rb_define_method(cHttpParser, "clear", HttpParser_clear, 0); @@ -964,14 +966,17 @@ void Init_unicorn_http(void) rb_define_singleton_method(cHttpParser, "max_header_len=", set_maxhdrlen, 1); - init_common_fields(); + init_common_fields(mark_ary); SET_GLOBAL(g_http_host, "HOST"); SET_GLOBAL(g_http_trailer, "TRAILER"); SET_GLOBAL(g_http_transfer_encoding, "TRANSFER_ENCODING"); SET_GLOBAL(g_content_length, "CONTENT_LENGTH"); SET_GLOBAL(g_http_connection, "CONNECTION"); id_set_backtrace = rb_intern("set_backtrace"); - init_unicorn_httpdate(); + init_unicorn_httpdate(mark_ary); + + OBJ_FREEZE(mark_ary); + rb_global_variable(&mark_ary); #ifndef HAVE_RB_HASH_CLEAR id_clear = rb_intern("clear"); diff --git a/lib/unicorn.rb b/lib/unicorn.rb index f122563..4bd7bda 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -95,7 +95,7 @@ module Unicorn # returns an array of strings representing TCP listen socket addresses # and Unix domain socket paths. This is useful for use with - # Raindrops::Middleware under Linux: http://raindrops.bogomips.org/ + # Raindrops::Middleware under Linux: https://bogomips.org/raindrops/ def self.listener_names Unicorn::HttpServer::LISTENERS.map do |io| Unicorn::SocketHelper.sock_name(io) diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb index 1e2b6e4..9f7f56f 100644 --- a/lib/unicorn/configurator.rb +++ b/lib/unicorn/configurator.rb @@ -49,10 +49,13 @@ class Unicorn::Configurator server.logger.error(m) end }, + :after_worker_ready => lambda { |server, worker| + server.logger.info("worker=#{worker.nr} ready") + }, :pid => nil, :preload_app => false, :check_client_connection => false, - :rewindable_input => true, # for Rack 2.x: (Rack::VERSION[0] <= 1), + :rewindable_input => true, :client_body_buffer_size => Unicorn::Const::MAX_BODY, } #:startdoc: @@ -172,6 +175,21 @@ class Unicorn::Configurator set_hook(:after_worker_exit, block_given? ? block : args[0], 3) end + # sets after_worker_ready hook to a given block. This block will be called + # by a worker process after it has been fully loaded, directly before it + # starts responding to requests: + # + # after_worker_ready do |server,worker| + # server.logger.info("worker #{worker.nr} ready, dropping privileges") + # worker.user('username', 'groupname') + # end + # + # Do not use Configurator#user if you rely on changing users in the + # after_worker_ready hook. + def after_worker_ready(*args, &block) + set_hook(:after_worker_ready, block_given? ? block : args[0]) + end + # sets before_fork got be a given Proc object. This Proc # object will be called by the master process before forking # each worker. @@ -487,13 +505,12 @@ class Unicorn::Configurator # Disabling rewindability can improve performance by lowering # I/O and memory usage for applications that accept uploads. # Keep in mind that the Rack 1.x spec requires - # \env[\"rack.input\"] to be rewindable, so this allows - # intentionally violating the current Rack 1.x spec. + # \env[\"rack.input\"] to be rewindable, + # but the Rack 2.x spec does not. # - # +rewindable_input+ defaults to +true+ when used with Rack 1.x for - # Rack conformance. When Rack 2.x is finalized, this will most - # likely default to +false+ while still conforming to the newer - # (less demanding) spec. + # +rewindable_input+ defaults to +true+ for compatibility. + # Setting it to +false+ may be safe for applications and + # frameworks developed for Rack 2.x and later. def rewindable_input(bool) set_bool(:rewindable_input, bool) end @@ -569,6 +586,10 @@ class Unicorn::Configurator # This switch will occur after calling the after_fork hook, and only # if the Worker#user method is not called in the after_fork hook # +group+ is optional and will not change if unspecified. + # + # Do not use Configurator#user if you rely on changing users in the + # after_worker_ready hook. Instead, you need to call Worker#user + # directly in after_worker_ready. def user(user, group = nil) # raises ArgumentError on invalid user/group Etc.getpwnam(user) diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb index c2086cb..4a2ccce 100644 --- a/lib/unicorn/http_server.rb +++ b/lib/unicorn/http_server.rb @@ -15,7 +15,7 @@ class Unicorn::HttpServer :before_fork, :after_fork, :before_exec, :listener_opts, :preload_app, :orig_app, :config, :ready_pipe, :user - attr_writer :after_worker_exit + attr_writer :after_worker_exit, :after_worker_ready attr_reader :pid, :logger include Unicorn::SocketHelper @@ -89,6 +89,7 @@ class Unicorn::HttpServer @self_pipe = [] @workers = {} # hash maps PIDs to Workers @sig_queue = [] # signal queue used for self-piping + @pid = nil # we try inheriting listeners first, so we bind them later. # we don't write the pid file until we've bound listeners in case @@ -644,7 +645,7 @@ class Unicorn::HttpServer trap(:USR1) { nr = -65536 } ready = readers.dup - @logger.info "worker=#{worker.nr} ready" + @after_worker_ready.call(self, worker) begin nr < 0 and reopen_worker_logs(worker.nr) diff --git a/lib/unicorn/oob_gc.rb b/lib/unicorn/oob_gc.rb index 5572e59..c4741a0 100644 --- a/lib/unicorn/oob_gc.rb +++ b/lib/unicorn/oob_gc.rb @@ -66,10 +66,9 @@ module Unicorn::OobGC end #:stopdoc: - PATH_INFO = "PATH_INFO" def process_client(client) super(client) # Unicorn::HttpServer#process_client - if OOBGC_PATH =~ OOBGC_ENV[PATH_INFO] && ((@@nr -= 1) <= 0) + if OOBGC_PATH =~ OOBGC_ENV['PATH_INFO'] && ((@@nr -= 1) <= 0) @@nr = OOBGC_INTERVAL OOBGC_ENV.clear disabled = GC.enable diff --git a/lib/unicorn/socket_helper.rb b/lib/unicorn/socket_helper.rb index 5371413..f52dde2 100644 --- a/lib/unicorn/socket_helper.rb +++ b/lib/unicorn/socket_helper.rb @@ -75,12 +75,15 @@ module Unicorn elsif respond_to?(:accf_arg) name = opt[:accept_filter] name = DEFAULTS[:accept_filter] if name.nil? + sock.listen(opt[:backlog]) + got = (sock.getsockopt(:SOL_SOCKET, :SO_ACCEPTFILTER) rescue nil).to_s + arg = accf_arg(name) begin - sock.setsockopt(:SOL_SOCKET, :SO_ACCEPTFILTER, accf_arg(name)) + sock.setsockopt(:SOL_SOCKET, :SO_ACCEPTFILTER, arg) rescue => e logger.error("#{sock_name(sock)} " \ "failed to set accept_filter=#{name} (#{e.inspect})") - end + end if arg != got end end diff --git a/lib/unicorn/stream_input.rb b/lib/unicorn/stream_input.rb index de5aeea..41d28a0 100644 --- a/lib/unicorn/stream_input.rb +++ b/lib/unicorn/stream_input.rb @@ -1,16 +1,17 @@ # -*- encoding: binary -*- -# When processing uploads, Unicorn may expose a StreamInput object under -# "rack.input" of the (future) Rack (2.x) environment. +# When processing uploads, unicorn may expose a StreamInput object under +# "rack.input" of the Rack environment when +# Unicorn::Configurator#rewindable_input is set to +false+ class Unicorn::StreamInput # The I/O chunk size (in +bytes+) for I/O operations where # the size cannot be user-specified when a method is called. # The default is 16 kilobytes. - @@io_chunk_size = Unicorn::Const::CHUNK_SIZE + @@io_chunk_size = Unicorn::Const::CHUNK_SIZE # :nodoc: # Initializes a new StreamInput object. You normally do not have to call # this unless you are writing an HTTP server. - def initialize(socket, request) + def initialize(socket, request) # :nodoc: @chunked = request.content_length.nil? @socket = socket @parser = request diff --git a/lib/unicorn/tee_input.rb b/lib/unicorn/tee_input.rb index 6f66162..2ccc2d9 100644 --- a/lib/unicorn/tee_input.rb +++ b/lib/unicorn/tee_input.rb @@ -1,6 +1,6 @@ # -*- encoding: binary -*- -# acts like tee(1) on an input input to provide a input-like stream +# Acts like tee(1) on an input input to provide a input-like stream # while providing rewindable semantics through a File/StringIO backing # store. On the first pass, the input is only read on demand so your # Rack application can use input notification (upload progress and @@ -9,22 +9,22 @@ # strict interpretation of Rack::Lint::InputWrapper functionality and # will not support any deviations from it. # -# When processing uploads, Unicorn exposes a TeeInput object under -# "rack.input" of the Rack environment. +# When processing uploads, unicorn exposes a TeeInput object under +# "rack.input" of the Rack environment by default. class Unicorn::TeeInput < Unicorn::StreamInput # The maximum size (in +bytes+) to buffer in memory before # resorting to a temporary file. Default is 112 kilobytes. - @@client_body_buffer_size = Unicorn::Const::MAX_BODY + @@client_body_buffer_size = Unicorn::Const::MAX_BODY # :nodoc: # sets the maximum size of request bodies to buffer in memory, # amounts larger than this are buffered to the filesystem - def self.client_body_buffer_size=(bytes) + def self.client_body_buffer_size=(bytes) # :nodoc: @@client_body_buffer_size = bytes end # returns the maximum size of request bodies to buffer in memory, # amounts larger than this are buffered to the filesystem - def self.client_body_buffer_size + def self.client_body_buffer_size # :nodoc: @@client_body_buffer_size end @@ -37,7 +37,7 @@ class Unicorn::TeeInput < Unicorn::StreamInput # Initializes a new TeeInput object. You normally do not have to call # this unless you are writing an HTTP server. - def initialize(socket, request) + def initialize(socket, request) # :nodoc: @len = request.content_length super @tmp = @len && @len <= @@client_body_buffer_size ? diff --git a/lib/unicorn/worker.rb b/lib/unicorn/worker.rb index 6748a2f..e22c1bf 100644 --- a/lib/unicorn/worker.rb +++ b/lib/unicorn/worker.rb @@ -111,9 +111,11 @@ class Unicorn::Worker # In most cases, you should be using the Unicorn::Configurator#user # directive instead. This method should only be used if you need # fine-grained control of exactly when you want to change permissions - # in your after_fork hooks. + # in your after_fork or after_worker_ready hooks, or if you want to + # use the chroot support. # - # Changes the worker process to the specified +user+ and +group+ + # Changes the worker process to the specified +user+ and +group+, + # and chroots to the current working directory if +chroot+ is set. # This is only intended to be called from within the worker # process from the +after_fork+ hook. This should be called in # the +after_fork+ hook after any privileged functions need to be @@ -123,7 +125,7 @@ class Unicorn::Worker # directly back to the caller (usually the +after_fork+ hook. # These errors commonly include ArgumentError for specifying an # invalid user/group and Errno::EPERM for insufficient privileges - def user(user, group = nil) + def user(user, group = nil, chroot = false) # we do not protect the caller, checking Process.euid == 0 is # insufficient because modern systems have fine-grained # capabilities. Let the caller handle any and all errors. @@ -134,6 +136,11 @@ class Unicorn::Worker Process.initgroups(user, gid) Process::GID.change_privilege(gid) end + if chroot + chroot = Dir.pwd if chroot == true + Dir.chroot(chroot) + Dir.chdir('/') + end Process.euid != uid and Process::UID.change_privilege(uid) @switched = true end diff --git a/t/test-lib.sh b/t/test-lib.sh index 28d6a88..7f97958 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -106,8 +106,8 @@ check_stderr () { # unicorn_setup unicorn_setup () { eval $(unused_listen) - port=$(expr $listen : '[^:]*:\([0-9]\+\)') - host=$(expr $listen : '\([^:]*\):[0-9]\+') + port=$(expr $listen : '[^:]*:\([0-9]*\)') + host=$(expr $listen : '\([^:][^:]*\):[0-9][0-9]*') rtmpfiles unicorn_config pid r_err r_out fifo tmp ok cat > $unicorn_config <<EOF diff --git a/test/exec/test_exec.rb b/test/exec/test_exec.rb index ca0b7bc..08f92ae 100644 --- a/test/exec/test_exec.rb +++ b/test/exec/test_exec.rb @@ -97,6 +97,9 @@ run lambda { |env| end def test_sd_listen_fds_emulation + # [ruby-core:69895] [Bug #11336] fixed by r51576 + return if RUBY_VERSION.to_f < 2.3 + File.open("config.ru", "wb") { |fp| fp.write(HI) } sock = TCPServer.new(@addr, @port) @@ -124,9 +127,7 @@ run lambda { |env| end ensure sock.close if sock - # disabled test on old Rubies: https://bugs.ruby-lang.org/issues/11336 - # [ruby-core:69895] [Bug #11336] fixed by r51576 - end if RUBY_VERSION.to_f >= 2.3 + end def test_inherit_listener_unspecified File.open("config.ru", "wb") { |fp| fp.write(HI) } @@ -142,7 +143,7 @@ run lambda { |env| res = hit(["http://#@addr:#@port/"]) assert_equal [ "HI\n" ], res assert_shutdown(pid) - assert_equal 1, sock.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).int, + assert sock.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).bool, 'unicorn should always set SO_KEEPALIVE on inherited sockets' ensure sock.close if sock diff --git a/test/unit/test_http_parser.rb b/test/unit/test_http_parser.rb index 7cbc0f8..31e6f71 100644 --- a/test/unit/test_http_parser.rb +++ b/test/unit/test_http_parser.rb @@ -851,24 +851,6 @@ class HttpParserTest < Test::Unit::TestCase assert_equal '', parser.env['HTTP_HOST'] end - # so we don't care about the portability of this test - # if it doesn't leak on Linux, it won't leak anywhere else - # unless your C compiler or platform is otherwise broken - LINUX_PROC_PID_STATUS = "/proc/self/status" - def test_memory_leak - match_rss = /^VmRSS:\s+(\d+)/ - if File.read(LINUX_PROC_PID_STATUS) =~ match_rss - before = $1.to_i - 1000000.times { Unicorn::HttpParser.new } - File.read(LINUX_PROC_PID_STATUS) =~ match_rss - after = $1.to_i - diff = after - before - assert(diff < 10000, "memory grew more than 10M: #{diff}") - end - end if RUBY_PLATFORM =~ /linux/ && - File.readable?(LINUX_PROC_PID_STATUS) && - !defined?(RUBY_ENGINE) - def test_memsize require 'objspace' if ObjectSpace.respond_to?(:memsize_of) diff --git a/test/unit/test_socket_helper.rb b/test/unit/test_socket_helper.rb index 7526e82..8699409 100644 --- a/test/unit/test_socket_helper.rb +++ b/test/unit/test_socket_helper.rb @@ -150,28 +150,31 @@ class TestSocketHelper < Test::Unit::TestCase end def test_tcp_defer_accept_default + return unless defined?(TCP_DEFER_ACCEPT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name) cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0] assert cur >= 1 - end if defined?(TCP_DEFER_ACCEPT) + end def test_tcp_defer_accept_disable + return unless defined?(TCP_DEFER_ACCEPT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name, :tcp_defer_accept => false) cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0] assert_equal 0, cur - end if defined?(TCP_DEFER_ACCEPT) + end def test_tcp_defer_accept_nr + return unless defined?(TCP_DEFER_ACCEPT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name, :tcp_defer_accept => 60) cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0] assert cur > 1 - end if defined?(TCP_DEFER_ACCEPT) + end def test_ipv6only port = begin @@ -186,6 +189,7 @@ class TestSocketHelper < Test::Unit::TestCase end def test_reuseport + return unless defined?(Socket::SO_REUSEPORT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name, :reuseport => true) @@ -193,5 +197,5 @@ class TestSocketHelper < Test::Unit::TestCase assert_operator cur, :>, 0 rescue Errno::ENOPROTOOPT # kernel does not support SO_REUSEPORT (older Linux) - end if defined?(Socket::SO_REUSEPORT) + end end diff --git a/test/unit/test_util.rb b/test/unit/test_util.rb index 4d17a16..dc6302e 100644 --- a/test/unit/test_util.rb +++ b/test/unit/test_util.rb @@ -69,7 +69,7 @@ class TestUtil < Test::Unit::TestCase } } tmp.close! - end if STDIN.respond_to?(:external_encoding) + end def test_reopen_logs_renamed_with_internal_encoding tmp = Tempfile.new('') @@ -101,5 +101,5 @@ class TestUtil < Test::Unit::TestCase } } tmp.close! - end if STDIN.respond_to?(:external_encoding) + end end |