about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--.olddoc.yml1
-rw-r--r--ISSUES18
-rw-r--r--Links2
-rw-r--r--ext/unicorn_http/common_field_optimization.h4
-rw-r--r--ext/unicorn_http/global_variables.h4
-rw-r--r--ext/unicorn_http/httpdate.c4
-rw-r--r--ext/unicorn_http/unicorn_http.rl13
-rw-r--r--lib/unicorn.rb2
-rw-r--r--lib/unicorn/configurator.rb35
-rw-r--r--lib/unicorn/http_server.rb5
-rw-r--r--lib/unicorn/oob_gc.rb3
-rw-r--r--lib/unicorn/socket_helper.rb7
-rw-r--r--lib/unicorn/stream_input.rb9
-rw-r--r--lib/unicorn/tee_input.rb14
-rw-r--r--lib/unicorn/worker.rb13
-rw-r--r--t/test-lib.sh4
-rw-r--r--test/exec/test_exec.rb9
-rw-r--r--test/unit/test_http_parser.rb18
-rw-r--r--test/unit/test_socket_helper.rb12
-rw-r--r--test/unit/test_util.rb4
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
diff --git a/ISSUES b/ISSUES
index 291441a..10df4d6 100644
--- a/ISSUES
+++ b/ISSUES
@@ -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...
diff --git a/Links b/Links
index 7c113c8..475a6c0 100644
--- a/Links
+++ b/Links
@@ -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