Class: WEBrick::GenericServer
Relationships & Source Files | |
Extension / Inclusion / Inheritance Descendants | |
Subclasses:
|
|
Inherits: | Object |
Defined in: | lib/webrick/ssl.rb, lib/webrick/server.rb |
Class Method Summary
-
.new(config = {}, default = Config::General) ⇒ GenericServer
constructor
Creates a new generic server from #config.
Instance Attribute Summary
-
#config
readonly
The server configuration.
-
#listeners
readonly
Sockets listening for connections.
-
#logger
readonly
The server logger.
-
#status
readonly
The server status.
-
#tokens
readonly
Tokens control the number of outstanding clients.
Instance Method Summary
-
#[](key)
Retrieves
key
from the configuration. -
#run(sock)
You must subclass
GenericServer
and implement #run which accepts a TCP client socket. -
#shutdown
Shuts down the server and all listening sockets.
-
#start(&block)
Starts the server and runs the
block
for each connection. -
#stop
Stops the server from accepting new connections.
Constructor Details
.new(config = {}, default = Config::General) ⇒ GenericServer
Creates a new generic server from #config. The default configuration comes from default
.
# File 'lib/webrick/server.rb', line 89
def initialize(config={}, default=Config::General) @config = default.dup.update(config) @status = :Stop @config[:Logger] ||= Log::new @logger = @config[:Logger] @tokens = Thread::SizedQueue.new(@config[:MaxClients]) @config[:MaxClients].times{ @tokens.push(nil) } webrickv = WEBrick::VERSION rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" @logger.info("WEBrick #{webrickv}") @logger.info("ruby #{rubyv}") @listeners = [] @shutdown_pipe = nil unless @config[:DoNotListen] if @config[:Listen] warn(":Listen option is deprecated; use GenericServer#listen") end listen(@config[:BindAddress], @config[:Port]) if @config[:Port] == 0 @config[:Port] = @listeners[0].addr[1] end end end
Instance Attribute Details
#config (readonly)
The server configuration
# File 'lib/webrick/server.rb', line 67
attr_reader :config
#listeners (readonly)
Sockets listening for connections.
# File 'lib/webrick/server.rb', line 83
attr_reader :listeners
#logger (readonly)
The server logger. This is independent from the HTTP access log.
# File 'lib/webrick/server.rb', line 72
attr_reader :logger
#status (readonly)
The server status. One of :Stop
, :Running
or :Shutdown
# File 'lib/webrick/server.rb', line 62
attr_reader :status
#tokens (readonly)
Tokens control the number of outstanding clients. The :MaxClients
configuration sets this.
# File 'lib/webrick/server.rb', line 78
attr_reader :tokens
Instance Method Details
#[](key)
Retrieves key
from the configuration
# File 'lib/webrick/server.rb', line 119
def [](key) @config[key] end
#run(sock)
You must subclass GenericServer
and implement #run which accepts a TCP client socket
# File 'lib/webrick/server.rb', line 242
def run(sock) @logger.fatal "run() must be provided by user." end
#shutdown
Shuts down the server and all listening sockets. New listeners must be provided to restart the server.
# File 'lib/webrick/server.rb', line 232
def shutdown stop alarm_shutdown_pipe(&:close) end
#start(&block)
Starts the server and runs the block
for each connection. This method does not return until the server is stopped from a signal handler or another thread using #stop or #shutdown.
If the block raises a subclass of StandardError the exception is logged and ignored. If an IOError or Errno::EBADF
exception is raised the exception is ignored. If an Exception subclass is raised the exception is logged and re-raised which stops the server.
To completely shut down a server call #shutdown from ensure:
server = WEBrick::GenericServer.new
# or WEBrick::HTTPServer.new
begin
server.start
ensure
server.shutdown
end
# File 'lib/webrick/server.rb', line 152
def start(&block) raise ServerError, "already started." if @status != :Stop server_type = @config[:ServerType] || SimpleServer setup_shutdown_pipe server_type.start{ @logger.info \ "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}" call_callback(:StartCallback) shutdown_pipe = @shutdown_pipe thgroup = ThreadGroup.new @status = :Running begin while @status == :Running begin sp = shutdown_pipe[0] if svrs = IO.select([sp, *@listeners], nil, nil, 2.0) if svrs[0].include? sp # swallow shutdown pipe buf = String.new nil while String === sp.read_nonblock([sp.nread, 8].max, buf, exception: false) break end svrs[0].each{|svr| @tokens.pop # blocks while no token is there. if sock = accept_client(svr) unless config[:DoNotReverseLookup].nil? sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup] end th = start_thread(sock, &block) th[:WEBrickThread] = true thgroup.add(th) else @tokens.push(nil) end } end rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex # if the listening socket was closed in GenericServer#shutdown, # IO::select raise it. rescue StandardError => ex msg = "#{ex.class}: #{ex.}\n\t#{ex.backtrace[0]}" @logger.error msg rescue Exception => ex @logger.fatal ex raise end end ensure cleanup_shutdown_pipe(shutdown_pipe) cleanup_listener @status = :Shutdown @logger.info "going to shutdown ..." thgroup.list.each{|th| th.join if th[:WEBrickThread] } call_callback(:StopCallback) @logger.info "#{self.class}#start done." @status = :Stop end } end
#stop
Stops the server from accepting new connections.
# File 'lib/webrick/server.rb', line 220
def stop if @status == :Running @status = :Shutdown end alarm_shutdown_pipe {|f| f.write_nonblock("\0")} end