favor IO#close_on_exec= over fcntl in 1.9+
[unicorn.git] / lib / unicorn.rb
blobcfa16568b808b451bf4a9366ba7082810e485af7
1 # -*- encoding: binary -*-
2 require 'etc'
3 require 'stringio'
4 require 'rack'
5 require 'kgio'
7 # :stopdoc:
8 # Unicorn module containing all of the classes (include C extensions) for
9 # running a Unicorn web server.  It contains a minimalist HTTP server with just
10 # enough functionality to service web application requests fast as possible.
11 # :startdoc:
13 # \Unicorn exposes very little of an user-visible API and most of its
14 # internals are subject to change.  \Unicorn is designed to host Rack
15 # applications, so applications should be written against the Rack SPEC
16 # and not \Unicorn internals.
17 module Unicorn
19   # Raised inside TeeInput when a client closes the socket inside the
20   # application dispatch.  This is always raised with an empty backtrace
21   # since there is nothing in the application stack that is responsible
22   # for client shutdowns/disconnects.  This exception is visible to Rack
23   # applications unless PrereadInput middleware is loaded.
24   class ClientShutdown < EOFError
25   end
27   # :stopdoc:
29   # This returns a lambda to pass in as the app, this does not "build" the
30   # app (which we defer based on the outcome of "preload_app" in the
31   # Unicorn config).  The returned lambda will be called when it is
32   # time to build the app.
33   def self.builder(ru, op)
34     # allow Configurator to parse cli switches embedded in the ru file
35     op = Unicorn::Configurator::RACKUP.merge!(:file => ru, :optparse => op)
37     # Op is going to get cleared before the returned lambda is called, so
38     # save this value so that it's still there when we need it:
39     no_default_middleware = op[:no_default_middleware]
41     # always called after config file parsing, may be called after forking
42     lambda do ||
43       inner_app = case ru
44       when /\.ru$/
45         raw = File.read(ru)
46         raw.sub!(/^__END__\n.*/, '')
47         eval("Rack::Builder.new {(\n#{raw}\n)}.to_app", TOPLEVEL_BINDING, ru)
48       else
49         require ru
50         Object.const_get(File.basename(ru, '.rb').capitalize)
51       end
53       pp({ :inner_app => inner_app }) if $DEBUG
55       return inner_app if no_default_middleware
57       # return value, matches rackup defaults based on env
58       # Unicorn does not support persistent connections, but Rainbows!
59       # and Zbatery both do.  Users accustomed to the Rack::Server default
60       # middlewares will need ContentLength/Chunked middlewares.
61       case ENV["RACK_ENV"]
62       when "development"
63         Rack::Builder.new do
64           use Rack::ContentLength
65           use Rack::Chunked
66           use Rack::CommonLogger, $stderr
67           use Rack::ShowExceptions
68           use Rack::Lint
69           run inner_app
70         end.to_app
71       when "deployment"
72         Rack::Builder.new do
73           use Rack::ContentLength
74           use Rack::Chunked
75           use Rack::CommonLogger, $stderr
76           run inner_app
77         end.to_app
78       else
79         inner_app
80       end
81     end
82   end
84   # returns an array of strings representing TCP listen socket addresses
85   # and Unix domain socket paths.  This is useful for use with
86   # Raindrops::Middleware under Linux: http://raindrops.bogomips.org/
87   def self.listener_names
88     Unicorn::HttpServer::LISTENERS.map do |io|
89       Unicorn::SocketHelper.sock_name(io)
90     end + Unicorn::HttpServer::NEW_LISTENERS
91   end
93   def self.log_error(logger, prefix, exc)
94     message = exc.message
95     message = message.dump if /[[:cntrl:]]/ =~ message
96     logger.error "#{prefix}: #{message} (#{exc.class})"
97     exc.backtrace.each { |line| logger.error(line) }
98   end
100   # remove this when we only support Ruby >= 2.0
101   def self.pipe # :nodoc:
102     Kgio::Pipe.new.each { |io| io.close_on_exec = true }
103   end
104   # :startdoc:
106 # :enddoc:
107 require 'unicorn/const'
108 require 'unicorn/socket_helper'
109 require 'unicorn/stream_input'
110 require 'unicorn/tee_input'
111 require 'unicorn/http_request'
112 require 'unicorn/configurator'
113 require 'unicorn/tmpio'
114 require 'unicorn/util'
115 require 'unicorn/http_response'
116 require 'unicorn/worker'
117 require 'unicorn/http_server'