thin 0.6.2-x86-mswin32-60 → 0.6.3-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of thin might be problematic. Click here for more details.
- data/CHANGELOG +34 -1
- data/bin/thin +2 -164
- data/example/config.ru +4 -1
- data/example/ramaze.ru +12 -0
- data/example/thin.god +70 -66
- data/lib/rack/adapter/rails.rb +0 -3
- data/lib/rack/handler/thin.rb +6 -1
- data/lib/thin.rb +13 -4
- data/lib/thin/command.rb +9 -5
- data/lib/thin/connection.rb +5 -14
- data/lib/thin/connectors/connector.rb +61 -0
- data/lib/thin/connectors/tcp_server.rb +29 -0
- data/lib/thin/connectors/unix_server.rb +48 -0
- data/lib/thin/controllers/cluster.rb +115 -0
- data/lib/thin/controllers/controller.rb +85 -0
- data/lib/thin/controllers/service.rb +73 -0
- data/lib/thin/controllers/service.sh.erb +39 -0
- data/lib/thin/daemonizing.rb +9 -4
- data/lib/thin/headers.rb +2 -2
- data/lib/thin/runner.rb +166 -0
- data/lib/thin/server.rb +109 -89
- data/lib/thin/stats.html.erb +216 -0
- data/lib/thin/stats.rb +1 -249
- data/lib/thin/version.rb +10 -3
- data/lib/thin_parser.so +0 -0
- data/spec/command_spec.rb +0 -1
- data/spec/configs/cluster.yml +9 -0
- data/spec/configs/single.yml +9 -0
- data/spec/{cluster_spec.rb → controllers/cluster_spec.rb} +22 -10
- data/spec/controllers/controller_spec.rb +85 -0
- data/spec/controllers/service_spec.rb +51 -0
- data/spec/daemonizing_spec.rb +73 -9
- data/spec/request/mongrel_spec.rb +39 -0
- data/spec/{request_spec.rb → request/parser_spec.rb} +11 -143
- data/spec/request/perf_spec.rb +50 -0
- data/spec/request/processing_spec.rb +46 -0
- data/spec/runner_spec.rb +135 -0
- data/spec/server/builder_spec.rb +38 -0
- data/spec/server/stopping_spec.rb +45 -0
- data/spec/server/tcp_spec.rb +54 -0
- data/spec/server/unix_socket_spec.rb +30 -0
- data/spec/spec_helper.rb +49 -16
- data/tasks/announce.rake +7 -3
- data/tasks/email.erb +8 -18
- data/tasks/stats.rake +21 -8
- metadata +33 -7
- data/lib/thin/cluster.rb +0 -123
- data/spec/server_spec.rb +0 -200
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
### BEGIN INIT INFO
|
3
|
+
# Provides: thin
|
4
|
+
# Required-Start: $local_fs $remote_fs
|
5
|
+
# Required-Stop: $local_fs $remote_fs
|
6
|
+
# Default-Start: 2 3 4 5
|
7
|
+
# Default-Stop: S 0 1 6
|
8
|
+
# Short-Description: thin initscript
|
9
|
+
# Description: thin
|
10
|
+
### END INIT INFO
|
11
|
+
|
12
|
+
# Original author: Forrest Robertson
|
13
|
+
|
14
|
+
# Do NOT "set -e"
|
15
|
+
|
16
|
+
DAEMON=<%= Command.script %>
|
17
|
+
SCRIPT_NAME=<%= INITD_PATH %>
|
18
|
+
CONFIG_PATH=<%= config_files_path %>
|
19
|
+
|
20
|
+
# Exit if the package is not installed
|
21
|
+
[ -x "$DAEMON" ] || exit 0
|
22
|
+
|
23
|
+
case "$1" in
|
24
|
+
start)
|
25
|
+
$DAEMON start --all $CONFIG_PATH
|
26
|
+
;;
|
27
|
+
stop)
|
28
|
+
$DAEMON stop --all $CONFIG_PATH
|
29
|
+
;;
|
30
|
+
restart)
|
31
|
+
$DAEMON restart --all $CONFIG_PATH
|
32
|
+
;;
|
33
|
+
*)
|
34
|
+
echo "Usage: $SCRIPT_NAME {start|stop|restart}" >&2
|
35
|
+
exit 3
|
36
|
+
;;
|
37
|
+
esac
|
38
|
+
|
39
|
+
:
|
data/lib/thin/daemonizing.rb
CHANGED
@@ -12,6 +12,9 @@ module Process
|
|
12
12
|
end
|
13
13
|
|
14
14
|
module Thin
|
15
|
+
# Raised when the pid file already exist starting as a daemon.
|
16
|
+
class PidFileExist < RuntimeError; end
|
17
|
+
|
15
18
|
# Module included in classes that can be turned into a daemon.
|
16
19
|
# Handle stuff like:
|
17
20
|
# * storing the PID in a file
|
@@ -31,15 +34,17 @@ module Thin
|
|
31
34
|
|
32
35
|
# Turns the current script into a daemon process that detaches from the console.
|
33
36
|
def daemonize
|
34
|
-
raise PlatformNotSupported, 'Daemonizing not supported on Windows'
|
35
|
-
raise ArgumentError,
|
37
|
+
raise PlatformNotSupported, 'Daemonizing not supported on Windows' if Thin.win?
|
38
|
+
raise ArgumentError, 'You must specify a pid_file to daemonize' unless @pid_file
|
39
|
+
raise PidFileExist, "#{@pid_file} already exist, seems like it's already running. " +
|
40
|
+
"Stop the process or delete #{@pid_file}." if File.exist?(@pid_file)
|
36
41
|
|
37
42
|
pwd = Dir.pwd # Current directory is changed during daemonization, so store it
|
38
43
|
|
39
|
-
Daemonize.daemonize(File.expand_path(@log_file))
|
44
|
+
Daemonize.daemonize(File.expand_path(@log_file), name)
|
40
45
|
|
41
46
|
Dir.chdir(pwd)
|
42
|
-
|
47
|
+
|
43
48
|
write_pid_file
|
44
49
|
|
45
50
|
trap('HUP') { restart }
|
data/lib/thin/headers.rb
CHANGED
data/lib/thin/runner.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Thin
|
5
|
+
# CLI runner.
|
6
|
+
# Parse options and send command to the correct Controller.
|
7
|
+
class Runner
|
8
|
+
COMMANDS = %w(start stop restart config)
|
9
|
+
LINUX_ONLY_COMMANDS = %w(install)
|
10
|
+
|
11
|
+
# Commands that wont load options from the config file
|
12
|
+
CONFIGLESS_COMMANDS = %w(config install)
|
13
|
+
|
14
|
+
# Parsed options
|
15
|
+
attr_accessor :options
|
16
|
+
|
17
|
+
# Name of the command to be runned.
|
18
|
+
attr_accessor :command
|
19
|
+
|
20
|
+
# Arguments to be passed to the command.
|
21
|
+
attr_accessor :arguments
|
22
|
+
|
23
|
+
# Return all available commands
|
24
|
+
def self.commands
|
25
|
+
commands = COMMANDS
|
26
|
+
commands += LINUX_ONLY_COMMANDS if Thin.linux?
|
27
|
+
commands
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(argv)
|
31
|
+
@argv = argv
|
32
|
+
|
33
|
+
# Default options values
|
34
|
+
@options = {
|
35
|
+
:chdir => Dir.pwd,
|
36
|
+
:environment => 'development',
|
37
|
+
:address => '0.0.0.0',
|
38
|
+
:port => 3000,
|
39
|
+
:timeout => 60,
|
40
|
+
:log => 'log/thin.log',
|
41
|
+
:pid => 'tmp/pids/thin.pid'
|
42
|
+
}
|
43
|
+
|
44
|
+
parse!
|
45
|
+
end
|
46
|
+
|
47
|
+
def parser
|
48
|
+
# NOTE: If you add an option here make sure the key in the +options+ hash is the
|
49
|
+
# same as the name of the command line option.
|
50
|
+
# +option+ keys are used to build the command line to launch other processes,
|
51
|
+
# see <tt>lib/thin/command.rb</tt>.
|
52
|
+
@parser ||= OptionParser.new do |opts|
|
53
|
+
opts.banner = "Usage: thin [options] #{self.class.commands.join('|')}"
|
54
|
+
|
55
|
+
opts.separator ""
|
56
|
+
opts.separator "Server options:"
|
57
|
+
|
58
|
+
opts.on("-a", "--address HOST", "bind to HOST address " +
|
59
|
+
"(default: #{@options[:address]})") { |host| @options[:address] = host }
|
60
|
+
opts.on("-p", "--port PORT", "use PORT (default: #{@options[:port]})") { |port| @options[:port] = port.to_i }
|
61
|
+
opts.on("-S", "--socket FILE", "bind to unix domain socket") { |file| @options[:socket] = file }
|
62
|
+
opts.on("-e", "--environment ENV", "Rails environment " +
|
63
|
+
"(default: #{@options[:environment]})") { |env| @options[:environment] = env }
|
64
|
+
opts.on("-c", "--chdir DIR", "Change to dir before starting") { |dir| @options[:chdir] = File.expand_path(dir) }
|
65
|
+
opts.on("-t", "--timeout SEC", "Request or command timeout in sec " +
|
66
|
+
"(default: #{@options[:timeout]})") { |sec| @options[:timeout] = sec.to_i }
|
67
|
+
opts.on("-r", "--rackup FILE", "Load a Rack config file instead of " +
|
68
|
+
"the Rails adapter") { |file| @options[:rackup] = file }
|
69
|
+
opts.on( "--prefix PATH", "Mount the app under PATH (start with /)") { |path| @options[:prefix] = path }
|
70
|
+
opts.on( "--stats PATH", "Mount the Stats adapter under PATH") { |path| @options[:stats] = path }
|
71
|
+
|
72
|
+
unless Thin.win? # Daemonizing not supported on Windows
|
73
|
+
opts.separator ""
|
74
|
+
opts.separator "Daemon options:"
|
75
|
+
|
76
|
+
opts.on("-d", "--daemonize", "Run daemonized in the background") { @options[:daemonize] = true }
|
77
|
+
opts.on("-l", "--log FILE", "File to redirect output " +
|
78
|
+
"(default: #{@options[:log]})") { |file| @options[:log] = file }
|
79
|
+
opts.on("-P", "--pid FILE", "File to store PID " +
|
80
|
+
"(default: #{@options[:pid]})") { |file| @options[:pid] = file }
|
81
|
+
opts.on("-u", "--user NAME", "User to run daemon as (use with -g)") { |user| @options[:user] = user }
|
82
|
+
opts.on("-g", "--group NAME", "Group to run daemon as (use with -u)") { |group| @options[:group] = group }
|
83
|
+
|
84
|
+
opts.separator ""
|
85
|
+
opts.separator "Cluster options:"
|
86
|
+
|
87
|
+
opts.on("-s", "--servers NUM", "Number of servers to start") { |num| @options[:servers] = num.to_i }
|
88
|
+
opts.on("-o", "--only NUM", "Send command to only one server of the cluster") { |only| @options[:only] = only }
|
89
|
+
opts.on("-C", "--config FILE", "Load options from config file") { |file| @options[:config] = file }
|
90
|
+
opts.on( "--all [DIR]", "Send command to each config files in DIR") { |dir| @options[:all] = dir } if Thin.linux?
|
91
|
+
end
|
92
|
+
|
93
|
+
opts.separator ""
|
94
|
+
opts.separator "Common options:"
|
95
|
+
|
96
|
+
opts.on_tail("-D", "--debug", "Set debbuging on") { $DEBUG = true }
|
97
|
+
opts.on_tail("-V", "--trace", "Set tracing on") { $TRACE = true }
|
98
|
+
opts.on_tail("-h", "--help", "Show this message") { puts opts; exit }
|
99
|
+
opts.on_tail('-v', '--version', "Show version") { puts Thin::SERVER; exit }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Parse the options.
|
104
|
+
def parse!
|
105
|
+
parser.parse! @argv
|
106
|
+
@command = @argv.shift
|
107
|
+
@arguments = @argv
|
108
|
+
end
|
109
|
+
|
110
|
+
# Parse the current shell arguments and run the command.
|
111
|
+
# Exits on error.
|
112
|
+
def run!
|
113
|
+
if self.class.commands.include?(@command)
|
114
|
+
run_command
|
115
|
+
elsif @command.nil?
|
116
|
+
puts "Command required"
|
117
|
+
puts @parser
|
118
|
+
exit 1
|
119
|
+
else
|
120
|
+
abort "Invalid command: #{@command}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Send the command to the controller: single instance or cluster.
|
125
|
+
def run_command
|
126
|
+
load_options_from_config_file! unless CONFIGLESS_COMMANDS.include?(@command)
|
127
|
+
|
128
|
+
# PROGRAM_NAME is relative to the current directory, so make sure
|
129
|
+
# we store and expand it before changing directory.
|
130
|
+
Command.script = File.expand_path($PROGRAM_NAME)
|
131
|
+
|
132
|
+
# Change the current directory ASAP so that all relative paths are
|
133
|
+
# relative to this one.
|
134
|
+
Dir.chdir(@options[:chdir]) unless CONFIGLESS_COMMANDS.include?(@command)
|
135
|
+
|
136
|
+
controller = case
|
137
|
+
when cluster? then Controllers::Cluster.new(@options)
|
138
|
+
when service? then Controllers::Service.new(@options)
|
139
|
+
else Controllers::Controller.new(@options)
|
140
|
+
end
|
141
|
+
|
142
|
+
if controller.respond_to?(@command)
|
143
|
+
controller.send(@command, *@arguments)
|
144
|
+
else
|
145
|
+
abort "Invalid options for command: #{@command}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# +true+ if we're controlling a cluster.
|
150
|
+
def cluster?
|
151
|
+
@options[:only] || @options[:servers]
|
152
|
+
end
|
153
|
+
|
154
|
+
# +true+ if we're acting a as system service.
|
155
|
+
def service?
|
156
|
+
@options.has_key?(:all) || @command == 'install'
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
def load_options_from_config_file!
|
161
|
+
if file = @options.delete(:config)
|
162
|
+
YAML.load_file(file).each { |key, value| @options[key.to_sym] = value }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/lib/thin/server.rb
CHANGED
@@ -1,68 +1,106 @@
|
|
1
1
|
module Thin
|
2
|
-
# The Thin HTTP server
|
3
|
-
# It listen for incoming request
|
2
|
+
# The uterly famous Thin HTTP server.
|
3
|
+
# It listen for incoming request through a given connector
|
4
4
|
# and forward all request to +app+.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# == TCP server
|
7
|
+
# Create a new TCP server on bound to <tt>host:port</tt> by specifiying +host+
|
8
|
+
# and +port+ as the first 2 arguments.
|
9
|
+
#
|
10
|
+
# Thin::Server.start('0.0.0.0', 3000, app)
|
11
|
+
#
|
12
|
+
# == UNIX domain server
|
13
|
+
# Create a new UNIX domain socket bound to +socket+ file by specifiying a filename
|
14
|
+
# as the first argument. Eg.: /tmp/thin.sock. If the first argument contains a <tt>/</tt>
|
15
|
+
# it will be assumed to be a UNIX socket.
|
16
|
+
#
|
17
|
+
# Thin::Server.start('/tmp/thin.sock', nil, app)
|
18
|
+
#
|
19
|
+
# == Using a custom connector
|
20
|
+
# You can implement your own way to connect the server to its client by creating your
|
21
|
+
# own Thin::Connectors::Connector class and pass it as the first argument.
|
22
|
+
#
|
23
|
+
# connector = Thin::Connectors::MyFancyConnector.new('galaxy://faraway:1345')
|
24
|
+
# Thin::Server.start(connector, nil, app)
|
25
|
+
#
|
26
|
+
# == Rack application (+app+)
|
27
|
+
# All requests will be processed through +app+ that must be a valid Rack adapter.
|
28
|
+
# A valid Rack adapter (application) must respond to <tt>call(env#Hash)</tt> and
|
29
|
+
# return an array of <tt>[status, headers, body]</tt>.
|
30
|
+
#
|
31
|
+
# == Building an app in place
|
32
|
+
# If a block is passed, a <tt>Rack::Builder</tt> instance
|
33
|
+
# will be passed to build the +app+. So you can do cool stuff like this:
|
34
|
+
#
|
35
|
+
# Thin::Server.start('0.0.0.0', 3000) do
|
36
|
+
# use Rack::CommonLogger
|
37
|
+
# use Rack::ShowExceptions
|
38
|
+
# map "/lobster" do
|
39
|
+
# use Rack::Lint
|
40
|
+
# run Rack::Lobster.new
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
8
44
|
class Server
|
9
45
|
include Logging
|
10
46
|
include Daemonizable
|
47
|
+
extend Forwardable
|
48
|
+
|
49
|
+
# Application (Rack adapter) called with the request that produces the response.
|
50
|
+
attr_accessor :app
|
11
51
|
|
12
|
-
#
|
13
|
-
attr_accessor :
|
52
|
+
# Connector handling the connections to the clients.
|
53
|
+
attr_accessor :connector
|
14
54
|
|
15
|
-
#
|
16
|
-
|
55
|
+
# Maximum number of seconds for incoming data to arrive before the connection
|
56
|
+
# is dropped.
|
57
|
+
def_delegators :@connector, :timeout, :timeout=
|
17
58
|
|
18
|
-
#
|
19
|
-
|
59
|
+
# Address and port on which the server is listening for connections.
|
60
|
+
def_delegators :@connector, :host, :port
|
20
61
|
|
21
|
-
#
|
22
|
-
|
62
|
+
# UNIX domain socket on which the server is listening for connections.
|
63
|
+
def_delegator :@connector, :socket
|
23
64
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
# end
|
38
|
-
# end.start
|
39
|
-
#
|
40
|
-
def initialize(host_or_socket, port=3000, app=nil, &block)
|
41
|
-
if host_or_socket.include?('/')
|
42
|
-
@socket = host_or_socket
|
43
|
-
else
|
44
|
-
@host = host_or_socket
|
45
|
-
@port = port.to_i
|
46
|
-
end
|
47
|
-
@app = app
|
48
|
-
@timeout = 60 # sec
|
49
|
-
@connections = []
|
65
|
+
def initialize(host_or_socket_or_connector, port=3000, app=nil, &block)
|
66
|
+
# Try to intelligently select which connector to use.
|
67
|
+
@connector = case
|
68
|
+
when host_or_socket_or_connector.is_a?(Connectors::Connector)
|
69
|
+
host_or_socket_or_connector
|
70
|
+
when host_or_socket_or_connector.include?('/')
|
71
|
+
Connectors::UnixServer.new(host_or_socket_or_connector)
|
72
|
+
else
|
73
|
+
Connectors::TcpServer.new(host_or_socket_or_connector, port.to_i)
|
74
|
+
end
|
75
|
+
|
76
|
+
@connector.server = self
|
77
|
+
@app = app
|
50
78
|
|
79
|
+
# Allow using Rack builder as a block
|
51
80
|
@app = Rack::Builder.new(&block).to_app if block
|
52
81
|
end
|
53
82
|
|
83
|
+
# Lil' shortcut to turn this:
|
84
|
+
#
|
85
|
+
# Server.new(...).start
|
86
|
+
#
|
87
|
+
# into this:
|
88
|
+
#
|
89
|
+
# Server.start(...)
|
90
|
+
#
|
54
91
|
def self.start(*args, &block)
|
55
92
|
new(*args, &block).start!
|
56
93
|
end
|
57
94
|
|
58
|
-
# Start the server and listen for connections
|
95
|
+
# Start the server and listen for connections.
|
96
|
+
# Also register signals:
|
97
|
+
# * INT calls +stop+ to shutdown gracefully.
|
98
|
+
# * TERM calls <tt>stop!</tt> to force shutdown.
|
59
99
|
def start
|
60
100
|
raise ArgumentError, 'app required' unless @app
|
61
101
|
|
62
102
|
trap('INT') { stop }
|
63
103
|
trap('TERM') { stop! }
|
64
|
-
|
65
|
-
at_exit { remove_socket_file } if @socket
|
66
104
|
|
67
105
|
# See http://rubyeventmachine.com/pub/rdoc/files/EPOLL.html
|
68
106
|
EventMachine.epoll
|
@@ -70,83 +108,65 @@ module Thin
|
|
70
108
|
log ">> Thin web server (v#{VERSION::STRING} codename #{VERSION::CODENAME})"
|
71
109
|
trace ">> Tracing ON"
|
72
110
|
|
73
|
-
|
111
|
+
log ">> Listening on #{@connector}, CTRL+C to stop"
|
112
|
+
@running = true
|
113
|
+
EventMachine.run { @connector.connect }
|
74
114
|
end
|
75
115
|
alias :start! :start
|
76
116
|
|
117
|
+
# == Gracefull shutdown
|
77
118
|
# Stops the server after processing all current connections.
|
119
|
+
# As soon as this method is called, the server stops accepting
|
120
|
+
# new requests and wait for all current connections to finish.
|
78
121
|
# Calling twice is the equivalent of calling <tt>stop!</tt>.
|
79
122
|
def stop
|
80
|
-
if @
|
81
|
-
|
82
|
-
else
|
83
|
-
@stopping = true
|
123
|
+
if @running
|
124
|
+
@running = false
|
84
125
|
|
85
126
|
# Do not accept anymore connection
|
86
|
-
|
127
|
+
@connector.disconnect
|
87
128
|
|
88
129
|
unless wait_for_connections_and_stop
|
89
130
|
# Still some connections running, schedule a check later
|
90
131
|
EventMachine.add_periodic_timer(1) { wait_for_connections_and_stop }
|
91
132
|
end
|
133
|
+
else
|
134
|
+
stop!
|
92
135
|
end
|
93
136
|
end
|
94
137
|
|
95
|
-
#
|
138
|
+
# == Force shutdown
|
139
|
+
# Stops the server closing all current connections right away.
|
140
|
+
# This doesn't wait for connection to finish their work and send data.
|
141
|
+
# All current requests will be dropped.
|
96
142
|
def stop!
|
97
143
|
log ">> Stopping ..."
|
98
144
|
|
99
|
-
@
|
145
|
+
@connector.close_connections
|
100
146
|
EventMachine.stop
|
101
147
|
|
102
|
-
|
148
|
+
@connector.close
|
103
149
|
end
|
150
|
+
|
151
|
+
def name
|
152
|
+
"thin server (#{@connector})"
|
153
|
+
end
|
154
|
+
alias :to_s :name
|
104
155
|
|
105
|
-
|
106
|
-
|
156
|
+
# Return +true+ if the server is running and ready to receive requests.
|
157
|
+
# Note that the server might still be running and return +false+ when
|
158
|
+
# shuting down and waiting for active connections to complete.
|
159
|
+
def running?
|
160
|
+
@running
|
107
161
|
end
|
108
162
|
|
109
|
-
protected
|
110
|
-
def start_server
|
111
|
-
if @socket
|
112
|
-
start_server_on_socket
|
113
|
-
else
|
114
|
-
start_server_on_host
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def start_server_on_host
|
119
|
-
log ">> Listening on #{@host}:#{@port}, CTRL+C to stop"
|
120
|
-
EventMachine.start_server(@host, @port, Connection, &method(:initialize_connection))
|
121
|
-
end
|
122
|
-
|
123
|
-
def start_server_on_socket
|
124
|
-
raise PlatformNotSupported, 'UNIX sockets not available on Windows' if Thin.win?
|
125
|
-
|
126
|
-
log ">> Listening on #{@socket}, CTRL+C to stop"
|
127
|
-
EventMachine.start_unix_domain_server(@socket, Connection, &method(:initialize_connection))
|
128
|
-
end
|
129
|
-
|
130
|
-
def initialize_connection(connection)
|
131
|
-
connection.server = self
|
132
|
-
connection.comm_inactivity_timeout = @timeout
|
133
|
-
connection.app = @app
|
134
|
-
connection.silent = @silent
|
135
|
-
connection.unix_socket = !@socket.nil?
|
136
|
-
|
137
|
-
@connections << connection
|
138
|
-
end
|
139
|
-
|
140
|
-
def remove_socket_file
|
141
|
-
File.delete(@socket) if @socket && File.exist?(@socket)
|
142
|
-
end
|
143
|
-
|
163
|
+
protected
|
144
164
|
def wait_for_connections_and_stop
|
145
|
-
if @
|
165
|
+
if @connector.empty?
|
146
166
|
stop!
|
147
167
|
true
|
148
168
|
else
|
149
|
-
log ">> Waiting for #{@
|
169
|
+
log ">> Waiting for #{@connector.size} connection(s) to finish, CTRL+C to force stop"
|
150
170
|
false
|
151
171
|
end
|
152
172
|
end
|