about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-01-02 22:29:12 +0000
committerEric Wong <e@80x24.org>2016-01-02 22:29:28 +0000
commit9e24bae3428f726800da2963a8f2695f7d4064cd (patch)
treedd4ce29efffa4f0da9c6d9ada903a277ec81196b /lib
parent1105a6957eed26a922a27bd6e6dbbc457524b664 (diff)
downloadyahns-9e24bae3428f726800da2963a8f2695f7d4064cd.tar.gz
There are likely yet-to-be-discovered bugs in here.
Also, keeping explicit #freeze calls for 2.2 users, since most
users have not migrated to 2.3, yet.
Diffstat (limited to 'lib')
-rw-r--r--lib/yahns.rb1
-rw-r--r--lib/yahns/acceptor.rb1
-rw-r--r--lib/yahns/cap_input.rb1
-rw-r--r--lib/yahns/client_expire_generic.rb1
-rw-r--r--lib/yahns/client_expire_tcpi.rb1
-rw-r--r--lib/yahns/config.rb33
-rw-r--r--lib/yahns/daemon.rb1
-rw-r--r--lib/yahns/fdmap.rb1
-rw-r--r--lib/yahns/http_client.rb3
-rw-r--r--lib/yahns/http_context.rb3
-rw-r--r--lib/yahns/http_response.rb3
-rw-r--r--lib/yahns/log.rb1
-rw-r--r--lib/yahns/max_body.rb1
-rw-r--r--lib/yahns/max_body/rewindable_wrapper.rb3
-rw-r--r--lib/yahns/max_body/wrapper.rb11
-rw-r--r--lib/yahns/openssl_client.rb1
-rw-r--r--lib/yahns/openssl_server.rb1
-rw-r--r--lib/yahns/proxy_http_response.rb11
-rw-r--r--lib/yahns/proxy_pass.rb5
-rw-r--r--lib/yahns/queue.rb1
-rw-r--r--lib/yahns/queue_egg.rb1
-rw-r--r--lib/yahns/queue_epoll.rb3
-rw-r--r--lib/yahns/queue_kqueue.rb3
-rw-r--r--lib/yahns/queue_quitter.rb1
-rw-r--r--lib/yahns/queue_quitter_pipe.rb1
-rw-r--r--lib/yahns/rack.rb5
-rw-r--r--lib/yahns/rackup_handler.rb2
-rw-r--r--lib/yahns/sendfile_compat.rb3
-rw-r--r--lib/yahns/server.rb1
-rw-r--r--lib/yahns/server_mp.rb2
-rw-r--r--lib/yahns/sigevent.rb1
-rw-r--r--lib/yahns/sigevent_efd.rb1
-rw-r--r--lib/yahns/sigevent_pipe.rb1
-rw-r--r--lib/yahns/socket_helper.rb2
-rw-r--r--lib/yahns/stream_file.rb1
-rw-r--r--lib/yahns/stream_input.rb7
-rw-r--r--lib/yahns/tcp_server.rb1
-rw-r--r--lib/yahns/tee_input.rb3
-rw-r--r--lib/yahns/tmpio.rb1
-rw-r--r--lib/yahns/unix_server.rb1
-rw-r--r--lib/yahns/wbuf.rb1
-rw-r--r--lib/yahns/wbuf_common.rb1
-rw-r--r--lib/yahns/wbuf_str.rb1
-rw-r--r--lib/yahns/worker.rb1
44 files changed, 89 insertions, 40 deletions
diff --git a/lib/yahns.rb b/lib/yahns.rb
index bbf86f2..b5f325b 100644
--- a/lib/yahns.rb
+++ b/lib/yahns.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 $stdout.sync = $stderr.sync = true
 
 require 'unicorn' # pulls in raindrops, kgio, fcntl, etc, stringio, and logger
diff --git a/lib/yahns/acceptor.rb b/lib/yahns/acceptor.rb
index 5745b73..6aea333 100644
--- a/lib/yahns/acceptor.rb
+++ b/lib/yahns/acceptor.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (see COPYING for details)
+# frozen_string_literal: true
 require_relative 'client_expire_tcpi'
 require_relative 'client_expire_generic'
 module Yahns::Acceptor # :nodoc:
diff --git a/lib/yahns/cap_input.rb b/lib/yahns/cap_input.rb
index a501958..ea0dc2d 100644
--- a/lib/yahns/cap_input.rb
+++ b/lib/yahns/cap_input.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
+# frozen_string_literal: true
 
 # This is used as the @input/env["rack.input"] when
 # input_buffering == true or :lazy
diff --git a/lib/yahns/client_expire_generic.rb b/lib/yahns/client_expire_generic.rb
index 5ffc779..6625b83 100644
--- a/lib/yahns/client_expire_generic.rb
+++ b/lib/yahns/client_expire_generic.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 module Yahns::ClientExpireGeneric # :nodoc:
   def __timestamp
     Yahns.now
diff --git a/lib/yahns/client_expire_tcpi.rb b/lib/yahns/client_expire_tcpi.rb
index c310800..d8a6ca6 100644
--- a/lib/yahns/client_expire_tcpi.rb
+++ b/lib/yahns/client_expire_tcpi.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require 'raindrops'
 
 # included in Yahns::HttpClient
diff --git a/lib/yahns/config.rb b/lib/yahns/config.rb
index 2b71fe5..5f0a2fd 100644
--- a/lib/yahns/config.rb
+++ b/lib/yahns/config.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 #
 # Implements a DSL for configuring a yahns server.
 # See http://yahns.yhbt.net/examples/yahns_multi.conf.rb for a full
@@ -98,10 +99,10 @@ class Yahns::Config # :nodoc:
 
   %w(atfork_prepare atfork_parent atfork_child).each do |fn|
     eval(
-    %Q(def #{fn}(*args, &blk);) <<
-    %Q(  _check_in_block([:worker_processes,:app], :#{fn});) <<
-    %Q(  _add_hook(:#{fn}, block_given? ? blk : args[0]);) <<
-    %Q(end)
+    "def #{fn}(*args, &blk);" \
+    "  _check_in_block([:worker_processes,:app], :#{fn});" \
+    "  _add_hook(:#{fn}, block_given? ? blk : args[0]);" \
+    'end'
     )
   end
 
@@ -279,10 +280,10 @@ class Yahns::Config # :nodoc:
   # queue parameters (Yahns::QueueEgg)
   %w(max_events worker_threads).each do |_v|
     eval(
-    %Q(def #{_v}(val);) <<
-    %Q(  _check_in_block(:queue, :#{_v});) <<
-    %Q(  @block.ctx.__send__("#{_v}=", _check_int(:#{_v}, val, 1));) <<
-    %Q(end)
+    "def #{_v}(val);" \
+    "  _check_in_block(:queue, :#{_v});" \
+    "  @block.ctx.__send__(%Q(#{_v}=), _check_int(:#{_v}, val, 1));" \
+    'end'
     )
   end
 
@@ -345,10 +346,10 @@ class Yahns::Config # :nodoc:
   # boolean config directives for app
   %w(check_client_connection persistent_connections).each do |_v|
     eval(
-    %Q(def #{_v}(bool);) <<
-    %Q(  _check_in_block(:app, :#{_v});) <<
-    %Q(  @block.ctx.__send__("#{_v}=", _check_bool(:#{_v}, bool));) <<
-    %Q(end)
+    "def #{_v}(bool);" \
+    "  _check_in_block(:app, :#{_v});" \
+    "  @block.ctx.__send__(%Q(#{_v}=), _check_bool(:#{_v}, bool));" \
+    'end'
     )
   end
 
@@ -374,10 +375,10 @@ class Yahns::Config # :nodoc:
     client_header_buffer_size: 1,
   }.each do |_v,minval|
     eval(
-    %Q(def #{_v}(val);) <<
-    %Q(  _check_in_block(:app, :#{_v});) <<
-    %Q(  @block.ctx.__send__("#{_v}=", _check_int(:#{_v}, val, #{minval}));) <<
-    %Q(end)
+    "def #{_v}(val);" \
+    "  _check_in_block(:app, :#{_v});" \
+    "  @block.ctx.__send__(%Q(#{_v}=), _check_int(:#{_v}, val, #{minval}));" \
+    'end'
     )
   end
 
diff --git a/lib/yahns/daemon.rb b/lib/yahns/daemon.rb
index fde384c..3abf47f 100644
--- a/lib/yahns/daemon.rb
+++ b/lib/yahns/daemon.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2014, all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require_relative '../yahns'
 
 module Yahns::Daemon # :nodoc:
diff --git a/lib/yahns/fdmap.rb b/lib/yahns/fdmap.rb
index 8ff1319..d930e3b 100644
--- a/lib/yahns/fdmap.rb
+++ b/lib/yahns/fdmap.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require 'thread'
 
 # only initialize this after forking, this is highly volatile and won't
diff --git a/lib/yahns/http_client.rb b/lib/yahns/http_client.rb
index 8a341f9..d8b4c6e 100644
--- a/lib/yahns/http_client.rb
+++ b/lib/yahns/http_client.rb
@@ -1,8 +1,9 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 class Yahns::HttpClient < Kgio::Socket # :nodoc:
-  NULL_IO = StringIO.new('') # :nodoc:
+  NULL_IO = StringIO.new.binmode # :nodoc:
 
   include Yahns::HttpResponse
   QEV_FLAGS = Yahns::Queue::QEV_RD # used by acceptor
diff --git a/lib/yahns/http_context.rb b/lib/yahns/http_context.rb
index eabc667..dc1c5d6 100644
--- a/lib/yahns/http_context.rb
+++ b/lib/yahns/http_context.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 
 # subclasses of Yahns::HttpClient will class extend this
 
@@ -79,7 +80,7 @@ module Yahns::HttpContext # :nodoc:
 
   def tmpio_for(len, env)
     # short requests are most common
-    return StringIO.new('') if len && len <= @client_body_buffer_size;
+    return StringIO.new.binmode if len && len <= @client_body_buffer_size;
 
     # too big or chunked, unknown length
     tmp = @input_buffer_tmpdir
diff --git a/lib/yahns/http_response.rb b/lib/yahns/http_response.rb
index 99bf664..57910b0 100644
--- a/lib/yahns/http_response.rb
+++ b/lib/yahns/http_response.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require_relative 'stream_file'
 require_relative 'wbuf_str'
 
@@ -134,7 +135,7 @@ module Yahns::HttpResponse # :nodoc:
       code = status.to_i
       msg = Rack::Utils::HTTP_STATUS_CODES[code]
       buf = "#{response_start}#{msg ? %Q(#{code} #{msg}) : status}\r\n" \
-            "Date: #{httpdate}\r\n"
+            "Date: #{httpdate}\r\n".dup
       headers.each do |key, value|
         case key
         when %r{\ADate\z}i
diff --git a/lib/yahns/log.rb b/lib/yahns/log.rb
index b8015c4..990978f 100644
--- a/lib/yahns/log.rb
+++ b/lib/yahns/log.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 
 # logging-related utility functions for all of yahns
 module Yahns::Log # :nodoc:
diff --git a/lib/yahns/max_body.rb b/lib/yahns/max_body.rb
index 101a4fb..1ff4a76 100644
--- a/lib/yahns/max_body.rb
+++ b/lib/yahns/max_body.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
+# frozen_string_literal: true
 
 # Middleware used to enforce client_max_body_size for TeeInput users.
 #
diff --git a/lib/yahns/max_body/rewindable_wrapper.rb b/lib/yahns/max_body/rewindable_wrapper.rb
index c8ea412..b7419e4 100644
--- a/lib/yahns/max_body/rewindable_wrapper.rb
+++ b/lib/yahns/max_body/rewindable_wrapper.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
+# frozen_string_literal: true
 class Yahns::MaxBody::RewindableWrapper < Yahns::MaxBody::Wrapper # :nodoc:
   def initialize(rack_input, limit)
     @orig_limit = limit
@@ -9,7 +10,7 @@ class Yahns::MaxBody::RewindableWrapper < Yahns::MaxBody::Wrapper # :nodoc:
 
   def rewind
     @limit = @orig_limit
-    @rbuf = ''
+    @rbuf = ''.dup
     @input.rewind
   end
 
diff --git a/lib/yahns/max_body/wrapper.rb b/lib/yahns/max_body/wrapper.rb
index e618568..b8ed8a6 100644
--- a/lib/yahns/max_body/wrapper.rb
+++ b/lib/yahns/max_body/wrapper.rb
@@ -1,11 +1,14 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
+# frozen_string_literal: true
 #
 # This is only used for chunked request bodies, which are rare
 class Yahns::MaxBody::Wrapper # :nodoc:
   def initialize(rack_input, limit)
-    @input, @limit, @rbuf = rack_input, limit, ''
+    @input = rack_input
+    @limit = limit
+    @rbuf = ''.dup
   end
 
   def each
@@ -16,7 +19,7 @@ class Yahns::MaxBody::Wrapper # :nodoc:
 
   # chunked encoding means this method behaves more like readpartial,
   # since Rack does not support a method named "readpartial"
-  def read(length = nil, rv = '')
+  def read(length = nil, rv = ''.dup)
     if length
       if length <= @rbuf.size
         length < 0 and raise ArgumentError, "negative length #{length} given"
@@ -53,7 +56,7 @@ class Yahns::MaxBody::Wrapper # :nodoc:
     end while true
   end
 
-  def checked_read(length = 16384, buf = '')
+  def checked_read(length = 16384, buf = ''.dup)
     if @input.read(length, buf)
       throw :yahns_EFBIG if ((@limit -= buf.size) < 0)
       return buf
@@ -62,7 +65,7 @@ class Yahns::MaxBody::Wrapper # :nodoc:
 
   def read_all
     rv = @rbuf.slice!(0, @rbuf.size)
-    tmp = ''
+    tmp = ''.dup
     while checked_read(16384, tmp)
       rv << tmp
     end
diff --git a/lib/yahns/openssl_client.rb b/lib/yahns/openssl_client.rb
index 246b407..c899f67 100644
--- a/lib/yahns/openssl_client.rb
+++ b/lib/yahns/openssl_client.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2014, all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (see COPYING for details)
+# frozen_string_literal: true
 
 require_relative 'sendfile_compat'
 
diff --git a/lib/yahns/openssl_server.rb b/lib/yahns/openssl_server.rb
index 3940892..ff372df 100644
--- a/lib/yahns/openssl_server.rb
+++ b/lib/yahns/openssl_server.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2014, all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (see COPYING for details)
+# frozen_string_literal: true
 
 require_relative 'acceptor'
 require_relative 'openssl_client'
diff --git a/lib/yahns/proxy_http_response.rb b/lib/yahns/proxy_http_response.rb
index 3858456..bfd6501 100644
--- a/lib/yahns/proxy_http_response.rb
+++ b/lib/yahns/proxy_http_response.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 
 # loaded by yahns/proxy_pass, this relies on Yahns::HttpResponse for
 # constants.
@@ -69,7 +70,7 @@ module Yahns::HttpResponse # :nodoc:
     alive = @hs.next? && self.class.persistent_connections
     response_headers = env['yahns.proxy_pass.response_headers']
 
-    res = "HTTP/1.1 #{msg ? %Q(#{code} #{msg}) : status}\r\n"
+    res = "HTTP/1.1 #{msg ? %Q(#{code} #{msg}) : status}\r\n".dup
     headers.each do |key,value| # n.b.: headers is an Array of 2-element Arrays
       case key
       when /\A(?:Connection|Keep-Alive)\z/i
@@ -123,7 +124,7 @@ module Yahns::HttpResponse # :nodoc:
 
       elsif kcar.chunked? # nasty chunked body
         req_res.proxy_trailers = nil # define to avoid warnings for now
-        buf = ''
+        buf = ''.dup
         case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf)
         when String
           kcar.filter_body(buf, tmp)
@@ -136,7 +137,7 @@ module Yahns::HttpResponse # :nodoc:
 
         buf = tmp
         req_res.proxy_trailers = [ buf, tlr = [] ]
-        rbuf = Thread.current[:yahns_rbuf] = ''
+        rbuf = Thread.current[:yahns_rbuf] = ''.dup
         until kcar.trailers(tlr, buf)
           case rv = req_res.kgio_tryread(0x2000, rbuf)
           when String
@@ -186,7 +187,7 @@ module Yahns::HttpResponse # :nodoc:
       end while len != 0
 
     elsif kcar.chunked? # nasty chunked body
-      buf = ''
+      buf = ''.dup
 
       unless req_res.proxy_trailers
         # are we done dechunking the main body, yet?
@@ -200,7 +201,7 @@ module Yahns::HttpResponse # :nodoc:
           return :wait_readable # self remains in :ignore, wait on upstream
         end until kcar.body_eof?
         req_res.proxy_trailers = [ tmp, [] ] # onto trailers!
-        rbuf = Thread.current[:yahns_rbuf] = ''
+        rbuf = Thread.current[:yahns_rbuf] = ''.dup
       end
 
       buf, tlr = *req_res.proxy_trailers
diff --git a/lib/yahns/proxy_pass.rb b/lib/yahns/proxy_pass.rb
index 728ab3e..c8eec84 100644
--- a/lib/yahns/proxy_pass.rb
+++ b/lib/yahns/proxy_pass.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require 'socket'
 require 'kgio'
 require 'kcar' # gem install kcar
@@ -24,7 +25,7 @@ class Yahns::ProxyPass # :nodoc:
     # we must reinitialize the thread-local rbuf if it may get beyond the
     # current thread
     def detach_rbuf!
-      Thread.current[:yahns_rbuf] = ''
+      Thread.current[:yahns_rbuf] = ''.dup
     end
 
     def yahns_step # yahns event loop entry point
@@ -225,7 +226,7 @@ class Yahns::ProxyPass # :nodoc:
     end
 
     req = "#{env['REQUEST_METHOD']} #{req} #{ver}\r\n" \
-          "X-Forwarded-For: #{env["REMOTE_ADDR"]}\r\n"
+          "X-Forwarded-For: #{env["REMOTE_ADDR"]}\r\n".dup
 
     # pass most HTTP_* headers through as-is
     chunked = false
diff --git a/lib/yahns/queue.rb b/lib/yahns/queue.rb
index 2abdc27..b49ff35 100644
--- a/lib/yahns/queue.rb
+++ b/lib/yahns/queue.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2014, all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 if SleepyPenguin.const_defined?(:Epoll)
   require_relative 'queue_epoll'
 else
diff --git a/lib/yahns/queue_egg.rb b/lib/yahns/queue_egg.rb
index 0d62c2e..c8f1670 100644
--- a/lib/yahns/queue_egg.rb
+++ b/lib/yahns/queue_egg.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 
 # this represents a Yahns::Queue before its vivified.  This only
 # lives in the parent process and should be clobbered after qc_vivify
diff --git a/lib/yahns/queue_epoll.rb b/lib/yahns/queue_epoll.rb
index c685fae..ba32bdc 100644
--- a/lib/yahns/queue_epoll.rb
+++ b/lib/yahns/queue_epoll.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 #
 # This is the dangerous, low-level epoll interface for sleepy_penguin
 # It is safe as long as you're aware of all potential concurrency
@@ -32,7 +33,7 @@ class Yahns::Queue < SleepyPenguin::Epoll::IO # :nodoc:
   end
 
   def thr_init
-    Thread.current[:yahns_rbuf] = ""
+    Thread.current[:yahns_rbuf] = ''.dup
     Thread.current[:yahns_fdmap] = @fdmap
     Thread.current[:yahns_queue] = self
   end
diff --git a/lib/yahns/queue_kqueue.rb b/lib/yahns/queue_kqueue.rb
index 2636cee..73e25ad 100644
--- a/lib/yahns/queue_kqueue.rb
+++ b/lib/yahns/queue_kqueue.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 #
 # This is the dangerous, low-level kqueue interface for sleepy_penguin
 # It is safe as long as you're aware of all potential concurrency
@@ -41,7 +42,7 @@ class Yahns::Queue < SleepyPenguin::Kqueue::IO # :nodoc:
   end
 
   def thr_init
-    Thread.current[:yahns_rbuf] = ""
+    Thread.current[:yahns_rbuf] = ''.dup
     Thread.current[:yahns_fdmap] = @fdmap
     Thread.current[:yahns_queue] = self
   end
diff --git a/lib/yahns/queue_quitter.rb b/lib/yahns/queue_quitter.rb
index f91ff58..34dc922 100644
--- a/lib/yahns/queue_quitter.rb
+++ b/lib/yahns/queue_quitter.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 
 require 'sleepy_penguin'
 
diff --git a/lib/yahns/queue_quitter_pipe.rb b/lib/yahns/queue_quitter_pipe.rb
index a886957..e5806e9 100644
--- a/lib/yahns/queue_quitter_pipe.rb
+++ b/lib/yahns/queue_quitter_pipe.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 #
 # POSIX pipe version, see queue_quitter.rb for the (preferred) eventfd one
 class Yahns::QueueQuitter # :nodoc:
diff --git a/lib/yahns/rack.rb b/lib/yahns/rack.rb
index 3ec3582..a2af3b3 100644
--- a/lib/yahns/rack.rb
+++ b/lib/yahns/rack.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require 'rack'
 class Yahns::Rack # :nodoc:
   attr_reader :preload
@@ -62,10 +63,10 @@ class Yahns::Rack # :nodoc:
       "rack.run_once" => false,
       "rack.hijack?" => true,
       "rack.version" => [ 1, 2 ],
-      "SCRIPT_NAME" => "",
+      "SCRIPT_NAME" => ''.dup,
 
       # this is not in the Rack spec, but some apps may rely on it
-      "SERVER_SOFTWARE" => "yahns"
+      "SERVER_SOFTWARE" => 'yahns'.dup
     }
   end
 
diff --git a/lib/yahns/rackup_handler.rb b/lib/yahns/rackup_handler.rb
index 3d7beab..a0756bb 100644
--- a/lib/yahns/rackup_handler.rb
+++ b/lib/yahns/rackup_handler.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2014, all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require_relative '../yahns'
 
 module Yahns::RackupHandler # :nodoc:
@@ -38,6 +39,7 @@ module Yahns::RackupHandler # :nodoc:
     Yahns::Server.new(cfg).start.join
   end
 
+  # this is called by Rack::Server
   def self.valid_options
     # these should be the most common options
     {
diff --git a/lib/yahns/sendfile_compat.rb b/lib/yahns/sendfile_compat.rb
index bd79c0c..c0269e9 100644
--- a/lib/yahns/sendfile_compat.rb
+++ b/lib/yahns/sendfile_compat.rb
@@ -1,12 +1,13 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 
 module Yahns::SendfileCompat # :nodoc:
   def trysendfile(io, offset, count)
     return 0 if count == 0
     count = 0x4000 if count > 0x4000
-    buf = Thread.current[:yahns_sfbuf] ||= ''
+    buf = Thread.current[:yahns_sfbuf] ||= ''.dup
     io.pos = offset
     str = io.read(count, buf) or return # nil for EOF
     n = 0
diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb
index 2db8baf..441d9de 100644
--- a/lib/yahns/server.rb
+++ b/lib/yahns/server.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require_relative 'queue_quitter'
 require_relative 'tcp_server'
 require_relative 'unix_server'
diff --git a/lib/yahns/server_mp.rb b/lib/yahns/server_mp.rb
index 6b5f4b6..f583812 100644
--- a/lib/yahns/server_mp.rb
+++ b/lib/yahns/server_mp.rb
@@ -1,6 +1,8 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
+
 module Yahns::ServerMP # :nodoc:
   EXIT_SIGS = [ :QUIT, :TERM, :INT ]
 
diff --git a/lib/yahns/sigevent.rb b/lib/yahns/sigevent.rb
index ff4ac27..b866ddd 100644
--- a/lib/yahns/sigevent.rb
+++ b/lib/yahns/sigevent.rb
@@ -1,5 +1,6 @@
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 if SleepyPenguin.const_defined?(:EventFD)
   require_relative 'sigevent_efd'
 else
diff --git a/lib/yahns/sigevent_efd.rb b/lib/yahns/sigevent_efd.rb
index ce3bf1b..001e669 100644
--- a/lib/yahns/sigevent_efd.rb
+++ b/lib/yahns/sigevent_efd.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 class Yahns::Sigevent < SleepyPenguin::EventFD # :nodoc:
   include Kgio::DefaultWaiters
   def self.new
diff --git a/lib/yahns/sigevent_pipe.rb b/lib/yahns/sigevent_pipe.rb
index cfdab37..59ac808 100644
--- a/lib/yahns/sigevent_pipe.rb
+++ b/lib/yahns/sigevent_pipe.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 class Yahns::Sigevent # :nodoc:
   attr_reader :to_io
   def initialize
diff --git a/lib/yahns/socket_helper.rb b/lib/yahns/socket_helper.rb
index c786801..3fa5ab6 100644
--- a/lib/yahns/socket_helper.rb
+++ b/lib/yahns/socket_helper.rb
@@ -1,6 +1,8 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
+
 # this is only meant for Yahns::Server
 module Yahns::SocketHelper # :nodoc:
 
diff --git a/lib/yahns/stream_file.rb b/lib/yahns/stream_file.rb
index acc9f12..834e30e 100644
--- a/lib/yahns/stream_file.rb
+++ b/lib/yahns/stream_file.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require_relative 'wbuf_common'
 
 class Yahns::StreamFile # :nodoc:
diff --git a/lib/yahns/stream_input.rb b/lib/yahns/stream_input.rb
index c913ae4..8c0964e 100644
--- a/lib/yahns/stream_input.rb
+++ b/lib/yahns/stream_input.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
+# frozen_string_literal: true
 
 # When processing uploads, Yahns may expose a StreamInput object under
 # "rack.input" of the (future) Rack (2.x) environment.
@@ -12,7 +13,7 @@ class Yahns::StreamInput # :nodoc:
     @client = client
     @parser = request
     @buf = request.buf
-    @rbuf = ''
+    @rbuf = ''.dup
     @bytes_read = 0
     filter_body(@rbuf, @buf) unless @buf.empty?
   end
@@ -36,7 +37,7 @@ class Yahns::StreamInput # :nodoc:
   # ios.read(length [, buffer]) will return immediately if there is
   # any data and only block when nothing is available (providing
   # IO#readpartial semantics).
-  def read(length = nil, rv = '')
+  def read(length = nil, rv = ''.dup)
     if length
       if length <= @rbuf.size
         length < 0 and raise ArgumentError, "negative length #{length} given"
@@ -79,7 +80,7 @@ class Yahns::StreamInput # :nodoc:
   def gets
     sep = $/
     if sep.nil?
-      read_all(rv = '')
+      read_all(rv = ''.dup)
       return rv.empty? ? nil : rv
     end
     re = /\A(.*?#{Regexp.escape(sep)})/
diff --git a/lib/yahns/tcp_server.rb b/lib/yahns/tcp_server.rb
index 20e1a35..a836d1f 100644
--- a/lib/yahns/tcp_server.rb
+++ b/lib/yahns/tcp_server.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (see COPYING for details)
+# frozen_string_literal: true
 require_relative 'acceptor'
 class Yahns::TCPServer < Kgio::TCPServer # :nodoc:
   include Yahns::Acceptor
diff --git a/lib/yahns/tee_input.rb b/lib/yahns/tee_input.rb
index 31ad9cc..7b69f13 100644
--- a/lib/yahns/tee_input.rb
+++ b/lib/yahns/tee_input.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
+# frozen_string_literal: true
 
 # acts like tee(1) on an input input to provide a input-like stream
 # while providing rewindable semantics through a File/StringIO backing
@@ -96,7 +97,7 @@ class Yahns::TeeInput < Yahns::StreamInput # :nodoc:
 
   # consumes the stream of the socket
   def consume!
-    junk = ""
+    junk = ''.dup
     rsize = __rsize
     nil while read(rsize, junk)
   end
diff --git a/lib/yahns/tmpio.rb b/lib/yahns/tmpio.rb
index dae3b30..33dc710 100644
--- a/lib/yahns/tmpio.rb
+++ b/lib/yahns/tmpio.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
+# frozen_string_literal: true
 require 'tmpdir'
 
 # some versions of Ruby had a broken Tempfile which didn't work
diff --git a/lib/yahns/unix_server.rb b/lib/yahns/unix_server.rb
index 9a4e72e..eb6d6a0 100644
--- a/lib/yahns/unix_server.rb
+++ b/lib/yahns/unix_server.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (see COPYING for details)
+# frozen_string_literal: true
 require_relative 'acceptor'
 class Yahns::UNIXServer < Kgio::UNIXServer # :nodoc:
   include Yahns::Acceptor
diff --git a/lib/yahns/wbuf.rb b/lib/yahns/wbuf.rb
index 1a24aab..565ac2d 100644
--- a/lib/yahns/wbuf.rb
+++ b/lib/yahns/wbuf.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require_relative 'wbuf_common'
 
 # This class is triggered whenever we need write buffering for clients
diff --git a/lib/yahns/wbuf_common.rb b/lib/yahns/wbuf_common.rb
index 8d81c0b..e80068b 100644
--- a/lib/yahns/wbuf_common.rb
+++ b/lib/yahns/wbuf_common.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 begin
   raise LoadError, "SENDFILE_BROKEN env set" if ENV["SENDFILE_BROKEN"]
   require 'sendfile'
diff --git a/lib/yahns/wbuf_str.rb b/lib/yahns/wbuf_str.rb
index 89dfd33..47c34b4 100644
--- a/lib/yahns/wbuf_str.rb
+++ b/lib/yahns/wbuf_str.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 require_relative 'wbuf_common'
 
 # we only use this for buffering the tiniest responses (which are already
diff --git a/lib/yahns/worker.rb b/lib/yahns/worker.rb
index d6e7364..14aba5f 100644
--- a/lib/yahns/worker.rb
+++ b/lib/yahns/worker.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 # Copyright (C) 2013-2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+# frozen_string_literal: true
 class Yahns::Worker # :nodoc:
   attr_accessor :nr
   attr_reader :to_io