Module: Unicorn

Included in:
Configurator
Defined in:
lib/unicorn.rb,
lib/unicorn/preread_input.rb

Overview

unicorn exposes very little of an user-visible API and most of its internals are subject to change. unicorn is designed to host Rack applications, so applications should be written against the Rack SPEC and not unicorn internals.

Defined Under Namespace

Modules: OobGC, Util Classes: Configurator, HttpServer, PrereadInput, StreamInput, TeeInput, Worker

Constant Summary collapse

ClientShutdown =

Raised inside TeeInput when a client closes the socket inside the application dispatch. This is always raised with an empty backtrace since there is nothing in the application stack that is responsible for client shutdowns/disconnects. This exception is visible to Rack applications unless PrereadInput middleware is loaded. This is a subclass of the standard EOFError class and applications should not rescue it explicitly, but rescue EOFError instead.

Class.new(EOFError)
F_SETPIPE_SZ =
1031

Class Method Summary collapse

Class Method Details

.builder(ru, op) ⇒ Object

This returns a lambda to pass in as the app, this does not “build” the app (which we defer based on the outcome of “preload_app” in the Unicorn config). The returned lambda will be called when it is time to build the app.


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/unicorn.rb', line 41

def self.builder(ru, op)
  # allow Configurator to parse cli switches embedded in the ru file
  op = Unicorn::Configurator::RACKUP.merge!(:file => ru, :optparse => op)
  if ru =~ /\.ru$/ && !defined?(Rack::Builder)
    abort "rack and Rack::Builder must be available for processing #{ru}"
  end

  # always called after config file parsing, may be called after forking
  lambda do |_, server|
    inner_app = case ru
    when /\.ru$/
      raw = File.read(ru)
      raw.sub!(/^__END__\n.*/, '')
      eval("Rack::Builder.new {(\n#{raw}\n)}.to_app", TOPLEVEL_BINDING, ru)
    else
      require ru
      Object.const_get(File.basename(ru, '.rb').capitalize)
    end

    if $DEBUG
      require 'pp'
      pp({ :inner_app => inner_app })
    end

    return inner_app unless server.default_middleware

    middleware = { # order matters
      ContentLength: nil,
      Chunked: nil,
      CommonLogger: [ $stderr ],
      ShowExceptions: nil,
      Lint: nil,
      TempfileReaper: nil,
    }

    # return value, matches rackup defaults based on env
    # Unicorn does not support persistent connections, but Rainbows!
    # and Zbatery both do.  Users accustomed to the Rack::Server default
    # middlewares will need ContentLength/Chunked middlewares.
    case ENV["RACK_ENV"]
    when "development"
    when "deployment"
      middleware.delete(:ShowExceptions)
      middleware.delete(:Lint)
    else
      return inner_app
    end
    Rack::Builder.new do
      middleware.each do |m, args|
        use(Rack.const_get(m), *args) if Rack.const_defined?(m)
      end
      run inner_app
    end.to_app
  end
end

.listener_namesObject

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: yhbt.net/raindrops/


100
101
102
103
104
# File 'lib/unicorn.rb', line 100

def self.listener_names
  Unicorn::HttpServer::LISTENERS.map do |io|
    Unicorn::SocketHelper.sock_name(io)
  end + Unicorn::HttpServer::NEW_LISTENERS
end

.log_error(logger, prefix, exc) ⇒ Object


106
107
108
109
110
111
# File 'lib/unicorn.rb', line 106

def self.log_error(logger, prefix, exc)
  message = exc.message
  message = message.dump if /[[:cntrl:]]/ =~ message
  logger.error "#{prefix}: #{message} (#{exc.class})"
  exc.backtrace.each { |line| logger.error(line) }
end

.pipeObject

:nodoc:


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/unicorn.rb', line 115

def self.pipe # :nodoc:
  Kgio::Pipe.new.each do |io|
    # shrink pipes to minimize impact on /proc/sys/fs/pipe-user-pages-soft
    # limits.
    if defined?(F_SETPIPE_SZ)
      begin
        io.fcntl(F_SETPIPE_SZ, Raindrops::PAGE_SIZE)
      rescue Errno::EINVAL
        # old kernel
      rescue Errno::EPERM
        # resizes fail if Linux is close to the pipe limit for the user
        # or if the user does not have permissions to resize
      end
    end
  end
end