starling 0.9.3 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +49 -0
- data/{License.txt → LICENSE} +1 -1
- data/README.rdoc +106 -0
- data/Rakefile +22 -4
- data/bin/starling +3 -1
- data/bin/starling_top +57 -0
- data/etc/sample-config.yml +9 -0
- data/etc/starling.redhat +63 -0
- data/etc/starling.ubuntu +71 -0
- data/lib/starling.rb +4 -4
- data/lib/starling/handler.rb +97 -56
- data/lib/starling/persistent_queue.rb +21 -26
- data/lib/starling/queue_collection.rb +6 -5
- data/lib/starling/server.rb +47 -137
- data/lib/starling/{runner.rb → server_runner.rb} +63 -24
- data/spec/starling_server_spec.rb +205 -0
- metadata +66 -42
- data/History.txt +0 -3
- data/Manifest.txt +0 -29
- data/README.txt +0 -42
- data/config/hoe.rb +0 -71
- data/config/requirements.rb +0 -15
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/script/txt2html +0 -74
- data/setup.rb +0 -1585
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/website.rake +0 -17
- data/test/test_helper.rb +0 -2
- data/test/test_persistent_queue.rb +0 -17
- data/test/test_starling.rb +0 -111
- data/website/index.html +0 -0
- data/website/index.txt +0 -66
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/stylesheets/screen.css +0 -138
- data/website/template.rhtml +0 -48
@@ -1,9 +1,3 @@
|
|
1
|
-
if RUBY_VERSION >= "1.8.6"
|
2
|
-
require 'thread'
|
3
|
-
else
|
4
|
-
require 'fastthread'
|
5
|
-
end
|
6
|
-
|
7
1
|
module StarlingServer
|
8
2
|
|
9
3
|
##
|
@@ -28,19 +22,20 @@ module StarlingServer
|
|
28
22
|
attr_reader :initial_bytes
|
29
23
|
attr_reader :total_items
|
30
24
|
attr_reader :logsize
|
25
|
+
attr_reader :current_age
|
31
26
|
|
32
27
|
##
|
33
28
|
# Create a new PersistentQueue at +persistence_path+/+queue_name+.
|
34
29
|
# If a queue log exists at that path, the Queue will be loaded from
|
35
30
|
# disk before being available for use.
|
36
|
-
|
31
|
+
|
37
32
|
def initialize(persistence_path, queue_name, debug = false)
|
38
33
|
@persistence_path = persistence_path
|
39
34
|
@queue_name = queue_name
|
40
|
-
@transaction_mutex = Mutex.new
|
41
35
|
@total_items = 0
|
42
36
|
super()
|
43
37
|
@initial_bytes = replay_transaction_log(debug)
|
38
|
+
@current_age = 0
|
44
39
|
end
|
45
40
|
|
46
41
|
##
|
@@ -55,31 +50,30 @@ module StarlingServer
|
|
55
50
|
end
|
56
51
|
|
57
52
|
@total_items += 1
|
58
|
-
super(value)
|
53
|
+
super([now_usec, value])
|
59
54
|
end
|
60
55
|
|
61
56
|
##
|
62
57
|
# Retrieves data from the queue.
|
63
|
-
|
58
|
+
|
64
59
|
def pop(log_trx = true)
|
65
60
|
raise NoTransactionLog if log_trx && !@trx
|
66
|
-
|
61
|
+
|
67
62
|
begin
|
68
63
|
rv = super(!log_trx)
|
69
64
|
rescue ThreadError
|
70
65
|
puts "WARNING: The queue was empty when trying to pop(). Technically this shouldn't ever happen. Probably a bug in the transactional underpinnings. Or maybe shutdown didn't happen cleanly at some point. Ignoring."
|
71
|
-
rv = ''
|
66
|
+
rv = [now_usec, '']
|
72
67
|
end
|
73
68
|
transaction "\001" if log_trx
|
74
|
-
rv
|
69
|
+
@current_age = (now_usec - rv[0]) / 1000
|
70
|
+
rv[1]
|
75
71
|
end
|
76
72
|
|
77
73
|
##
|
78
74
|
# Safely closes the transactional queue.
|
79
|
-
|
80
|
-
def close
|
81
|
-
@transaction_mutex.lock
|
82
75
|
|
76
|
+
def close
|
83
77
|
# Ok, yeah, this is lame, and is *technically* a race condition. HOWEVER,
|
84
78
|
# the QueueCollection *should* have stopped processing requests, and I don't
|
85
79
|
# want to add yet another Mutex around all the push and pop methods. So we
|
@@ -103,8 +97,10 @@ module StarlingServer
|
|
103
97
|
|
104
98
|
def rotate_log #:nodoc:
|
105
99
|
@trx.close
|
106
|
-
|
100
|
+
backup_logfile = "#{log_path}.#{Time.now.to_i}"
|
101
|
+
File.rename(log_path, backup_logfile)
|
107
102
|
reopen_log
|
103
|
+
File.unlink(backup_logfile)
|
108
104
|
end
|
109
105
|
|
110
106
|
def replay_transaction_log(debug) #:nodoc:
|
@@ -142,15 +138,14 @@ module StarlingServer
|
|
142
138
|
def transaction(data) #:nodoc:
|
143
139
|
raise "no transaction log handle. that totally sucks." unless @trx
|
144
140
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
141
|
+
@trx.write_nonblock data
|
142
|
+
@logsize += data.size
|
143
|
+
rotate_log if @logsize > SOFT_LOG_MAX_SIZE && self.length == 0
|
144
|
+
end
|
145
|
+
|
146
|
+
def now_usec
|
147
|
+
now = Time.now
|
148
|
+
now.to_i * 1000000 + now.usec
|
154
149
|
end
|
155
150
|
end
|
156
151
|
end
|
@@ -7,20 +7,21 @@ module StarlingServer
|
|
7
7
|
|
8
8
|
##
|
9
9
|
# QueueCollection is a proxy to a collection of PersistentQueue instances.
|
10
|
-
|
10
|
+
|
11
11
|
class QueueCollection
|
12
12
|
|
13
13
|
##
|
14
14
|
# Create a new QueueCollection at +path+
|
15
|
-
|
15
|
+
|
16
16
|
def initialize(path)
|
17
17
|
unless File.directory?(path) && File.writable?(path)
|
18
|
-
raise InaccessibleQueuePath.new(path)
|
18
|
+
raise InaccessibleQueuePath.new("'#{path}' must exist and be read-writable by #{Etc.getpwuid(Process.uid).name}.")
|
19
19
|
end
|
20
20
|
|
21
21
|
@shutdown_mutex = Mutex.new
|
22
22
|
|
23
23
|
@path = path
|
24
|
+
@logger = StarlingServer::Base.logger
|
24
25
|
|
25
26
|
@queues = {}
|
26
27
|
@queue_init_mutexes = {}
|
@@ -39,7 +40,7 @@ module StarlingServer
|
|
39
40
|
@stats[:total_items] += 1
|
40
41
|
|
41
42
|
queue.push(data)
|
42
|
-
|
43
|
+
|
43
44
|
return true
|
44
45
|
end
|
45
46
|
|
@@ -60,7 +61,7 @@ module StarlingServer
|
|
60
61
|
end
|
61
62
|
|
62
63
|
##
|
63
|
-
# Returns all active queues.
|
64
|
+
# Returns all active queues.
|
64
65
|
|
65
66
|
def queues(key=nil)
|
66
67
|
return nil if @shutdown_mutex.locked?
|
data/lib/starling/server.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'logger'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'eventmachine'
|
5
|
+
require 'analyzer_tools/syslog_logger'
|
3
6
|
|
4
7
|
here = File.dirname(__FILE__)
|
5
8
|
|
@@ -8,13 +11,9 @@ require File.join(here, 'handler')
|
|
8
11
|
|
9
12
|
module StarlingServer
|
10
13
|
|
11
|
-
VERSION = "0.9.
|
12
|
-
|
13
|
-
class StopServer < Exception #:nodoc:
|
14
|
-
end
|
15
|
-
|
14
|
+
VERSION = "0.9.8"
|
15
|
+
|
16
16
|
class Base
|
17
|
-
|
18
17
|
attr_reader :logger
|
19
18
|
|
20
19
|
DEFAULT_HOST = '127.0.0.1'
|
@@ -36,11 +35,10 @@ module StarlingServer
|
|
36
35
|
# [:loglevel] Logger verbosity. Default is Logger::ERROR.
|
37
36
|
#
|
38
37
|
# Other options are ignored.
|
39
|
-
|
38
|
+
|
40
39
|
def self.start(opts = {})
|
41
40
|
server = self.new(opts)
|
42
|
-
|
43
|
-
[server, acceptor]
|
41
|
+
server.run
|
44
42
|
end
|
45
43
|
|
46
44
|
##
|
@@ -48,32 +46,20 @@ module StarlingServer
|
|
48
46
|
# process requests.
|
49
47
|
#
|
50
48
|
# +opts+ is as for +start+
|
51
|
-
|
52
|
-
def initialize(opts = {})
|
53
|
-
@opts = { :host => DEFAULT_HOST,
|
54
|
-
:port => DEFAULT_PORT,
|
55
|
-
:path => DEFAULT_PATH,
|
56
|
-
:timeout => DEFAULT_TIMEOUT }.merge(opts)
|
57
|
-
|
58
|
-
@logger = case @opts[:logger]
|
59
|
-
when IO, String; Logger.new(opts[:logger])
|
60
|
-
when Logger; opts[:logger]
|
61
|
-
else; Logger.new(STDERR)
|
62
|
-
end
|
63
|
-
|
64
|
-
@logger.level = @opts[:log_level] || Logger::ERROR
|
65
49
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
50
|
+
def initialize(opts = {})
|
51
|
+
@opts = {
|
52
|
+
:host => DEFAULT_HOST,
|
53
|
+
:port => DEFAULT_PORT,
|
54
|
+
:path => DEFAULT_PATH,
|
55
|
+
:timeout => DEFAULT_TIMEOUT,
|
56
|
+
:server => self
|
57
|
+
}.merge(opts)
|
71
58
|
|
72
|
-
@
|
59
|
+
@stats = Hash.new(0)
|
73
60
|
|
74
|
-
@
|
61
|
+
FileUtils.mkdir_p(@opts[:path])
|
75
62
|
|
76
|
-
@stats = Hash.new(0)
|
77
63
|
end
|
78
64
|
|
79
65
|
##
|
@@ -82,127 +68,51 @@ module StarlingServer
|
|
82
68
|
def run
|
83
69
|
@stats[:start_time] = Time.now
|
84
70
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
graceful_shutdown
|
71
|
+
@@logger = case @opts[:logger]
|
72
|
+
when IO, String; Logger.new(@opts[:logger])
|
73
|
+
when Logger; @opts[:logger]
|
74
|
+
else; Logger.new(STDERR)
|
75
|
+
end
|
76
|
+
@@logger = SyslogLogger.new(@opts[:syslog_channel]) if @opts[:syslog_channel]
|
77
|
+
|
78
|
+
begin
|
79
|
+
@opts[:queue] = QueueCollection.new(@opts[:path])
|
80
|
+
rescue InaccessibleQueuePath => e
|
81
|
+
puts "Error: #{e.message}"
|
82
|
+
exit 1
|
83
|
+
end
|
84
|
+
@@logger.level = @opts[:log_level] || Logger::ERROR
|
85
|
+
|
86
|
+
@@logger.info "Starling STARTUP on #{@opts[:host]}:#{@opts[:port]}"
|
87
|
+
|
88
|
+
EventMachine.epoll
|
89
|
+
EventMachine.set_descriptor_table_size(4096)
|
90
|
+
EventMachine.run do
|
91
|
+
EventMachine.start_server(@opts[:host], @opts[:port], Handler, @opts)
|
110
92
|
end
|
111
93
|
|
112
|
-
|
94
|
+
# code here will get executed on shutdown:
|
95
|
+
@opts[:queue].close
|
113
96
|
end
|
114
97
|
|
98
|
+
def self.logger
|
99
|
+
@@logger
|
100
|
+
end
|
101
|
+
|
102
|
+
|
115
103
|
##
|
116
104
|
# Stop accepting new connections and shutdown gracefully.
|
117
105
|
|
118
106
|
def stop
|
119
|
-
|
120
|
-
stopper.priority = Thread.current.priority + 10
|
107
|
+
EventMachine.stop_event_loop
|
121
108
|
end
|
122
109
|
|
123
110
|
def stats(stat = nil) #:nodoc:
|
124
111
|
case stat
|
125
112
|
when nil; @stats
|
126
|
-
when :connections;
|
113
|
+
when :connections; 1
|
127
114
|
else; @stats[stat]
|
128
115
|
end
|
129
116
|
end
|
130
|
-
|
131
|
-
private
|
132
|
-
|
133
|
-
def accept_connection #:nodoc:
|
134
|
-
client = @socket.accept
|
135
|
-
|
136
|
-
@stats[:total_connections] += 1
|
137
|
-
|
138
|
-
thread = Thread.new(client) { |c| spawn_handler(c) }
|
139
|
-
thread[:last_activity] = Time.now
|
140
|
-
@workers.add(thread)
|
141
|
-
end
|
142
|
-
|
143
|
-
def spawn_handler(client) #:nodoc:
|
144
|
-
begin
|
145
|
-
queue_handler = Handler.new(client, self, @queue_collection)
|
146
|
-
queue_handler.run
|
147
|
-
rescue EOFError, Errno::EBADF, Errno::ECONNRESET, Errno::EINVAL, Errno::EPIPE
|
148
|
-
begin
|
149
|
-
client.close
|
150
|
-
rescue Object => e
|
151
|
-
logger.warn "Got exception while closing socket after connection error: #{e}"
|
152
|
-
logger.debug e.backtrace.join("\n")
|
153
|
-
end
|
154
|
-
rescue TimeoutError => reason
|
155
|
-
begin
|
156
|
-
logger.info "Shutdown due to timeout: #{reason.message}"
|
157
|
-
client.close
|
158
|
-
rescue Object => e
|
159
|
-
logger.warn "Got exception while closing socket after timeout: #{e}"
|
160
|
-
logger.debug e.backtrace.join("\n")
|
161
|
-
end
|
162
|
-
rescue Errno::EMFILE
|
163
|
-
cull_workers('Too many open files or sockets')
|
164
|
-
rescue Object => e
|
165
|
-
logger.error("Unknown error: #{e}")
|
166
|
-
logger.debug(e.backtrace.join("\n"))
|
167
|
-
ensure
|
168
|
-
begin
|
169
|
-
client.close
|
170
|
-
rescue Object => e
|
171
|
-
logger.info "Got exception while closing socket: #{e}"
|
172
|
-
logger.debug e.backtrace.join("\n")
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def cull_workers(reason='unknown') #:nodoc:
|
178
|
-
if @workers.list.length > 0
|
179
|
-
logger.info "#{Time.now}: Reaping #{@workers.list.length} threads because of #{reason}"
|
180
|
-
error_msg = "Starling timed out this thread: #{reason}"
|
181
|
-
mark = Time.now
|
182
|
-
@workers.list.each do |w|
|
183
|
-
w[:last_activity] = Time.now if not w[:last_activity]
|
184
|
-
|
185
|
-
if mark - w[:last_activity] > @timeout
|
186
|
-
logger.warn "Thread #{w.inspect} has been idle for #{mark - w[:last_activity]}s, killing."
|
187
|
-
w.raise(TimeoutError.new(error_msg))
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
return @workers.list.length
|
193
|
-
end
|
194
|
-
|
195
|
-
def graceful_shutdown #:nodoc:
|
196
|
-
@workers.list.each do |w|
|
197
|
-
w[:shutdown] = true
|
198
|
-
end
|
199
|
-
|
200
|
-
@queue_collection.close
|
201
|
-
|
202
|
-
while cull_workers("shutdown") > 0
|
203
|
-
logger.info "Waiting for #{@workers.list.length} requests to finish, could take #{@timeout} seconds."
|
204
|
-
sleep 0.5
|
205
|
-
end
|
206
|
-
end
|
207
117
|
end
|
208
118
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'server')
|
2
2
|
require 'optparse'
|
3
|
+
require 'yaml'
|
3
4
|
|
4
5
|
module StarlingServer
|
5
6
|
class Runner
|
@@ -10,11 +11,16 @@ module StarlingServer
|
|
10
11
|
def self.run
|
11
12
|
new
|
12
13
|
end
|
13
|
-
|
14
|
+
|
15
|
+
def self.shutdown
|
16
|
+
@@instance.shutdown
|
17
|
+
end
|
18
|
+
|
14
19
|
def initialize
|
20
|
+
@@instance = self
|
15
21
|
parse_options
|
16
22
|
|
17
|
-
@process = ProcessHelper.new(options[:
|
23
|
+
@process = ProcessHelper.new(options[:logger], options[:pid_file], options[:user], options[:group])
|
18
24
|
|
19
25
|
pid = @process.running?
|
20
26
|
if pid
|
@@ -27,29 +33,50 @@ module StarlingServer
|
|
27
33
|
start
|
28
34
|
end
|
29
35
|
|
36
|
+
def load_config_file(filename)
|
37
|
+
YAML.load(File.open(filename))['starling'].each do |key, value|
|
38
|
+
# alias some keys
|
39
|
+
case key
|
40
|
+
when "queue_path" then key = "path"
|
41
|
+
when "log_file" then key = "logger"
|
42
|
+
end
|
43
|
+
options[key.to_sym] = value
|
44
|
+
|
45
|
+
if options[:log_level].instance_of?(String)
|
46
|
+
options[:log_level] = Logger.const_get(options[:log_level])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
30
51
|
def parse_options
|
31
52
|
self.options = { :host => '127.0.0.1',
|
32
53
|
:port => 22122,
|
33
|
-
:path => File.join(
|
34
|
-
:log_level =>
|
54
|
+
:path => File.join('', 'var', 'spool', 'starling'),
|
55
|
+
:log_level => Logger::INFO,
|
35
56
|
:daemonize => false,
|
36
|
-
:
|
57
|
+
:timeout => 0,
|
58
|
+
:pid_file => File.join('', 'var', 'run', 'starling.pid') }
|
37
59
|
|
38
60
|
OptionParser.new do |opts|
|
39
61
|
opts.summary_width = 25
|
40
62
|
|
41
63
|
opts.banner = "Starling (#{StarlingServer::VERSION})\n\n",
|
42
|
-
"usage: starling [
|
43
|
-
" [-d [-P pidfile]] [-u user] [-g group] [-l log]\n",
|
64
|
+
"usage: starling [options...]\n",
|
44
65
|
" starling --help\n",
|
45
66
|
" starling --version\n"
|
46
67
|
|
47
68
|
opts.separator ""
|
48
69
|
opts.separator "Configuration:"
|
70
|
+
|
71
|
+
opts.on("-f", "--config FILENAME",
|
72
|
+
"Config file (yaml) to load") do |filename|
|
73
|
+
load_config_file(filename)
|
74
|
+
end
|
75
|
+
|
49
76
|
opts.on("-q", "--queue_path PATH",
|
50
77
|
:REQUIRED,
|
51
78
|
"Path to store Starling queue logs", "(default: #{options[:path]})") do |queue_path|
|
52
|
-
options[:path] = queue_path
|
79
|
+
options[:path] = File.expand_path(queue_path)
|
53
80
|
end
|
54
81
|
|
55
82
|
opts.separator ""; opts.separator "Network:"
|
@@ -68,26 +95,36 @@ module StarlingServer
|
|
68
95
|
options[:daemonize] = true
|
69
96
|
end
|
70
97
|
|
71
|
-
opts.on("-PFILE", "--pid
|
72
|
-
options[:pid_file] = pid_file
|
98
|
+
opts.on("-PFILE", "--pid FILENAME", "save PID in FILENAME when using -d option.", "(default: #{options[:pid_file]})") do |pid_file|
|
99
|
+
options[:pid_file] = File.expand_path(pid_file)
|
73
100
|
end
|
74
101
|
|
75
|
-
opts.on("-u", "--user USER",
|
76
|
-
options[:user] = user
|
102
|
+
opts.on("-u", "--user USER", "User to run as") do |user|
|
103
|
+
options[:user] = user.to_i == 0 ? Etc.getpwnam(user).uid : user.to_i
|
77
104
|
end
|
78
105
|
|
79
106
|
opts.on("-gGROUP", "--group GROUP", "Group to run as") do |group|
|
80
|
-
options[:group] = group
|
107
|
+
options[:group] = group.to_i == 0 ? Etc.getgrnam(group).gid : group.to_i
|
81
108
|
end
|
82
109
|
|
83
110
|
opts.separator ""; opts.separator "Logging:"
|
84
111
|
|
85
|
-
opts.on("-
|
86
|
-
options[:
|
112
|
+
opts.on("-L", "--log [FILE]", "Path to print debugging information.") do |log_path|
|
113
|
+
options[:logger] = File.expand_path(log_path)
|
114
|
+
end
|
115
|
+
|
116
|
+
opts.on("-l", "--syslog CHANNEL", "Write logs to the syslog instead of a log file.") do |channel|
|
117
|
+
options[:syslog_channel] = channel
|
118
|
+
end
|
119
|
+
|
120
|
+
opts.on("-v", "Increase logging verbosity (may be used multiple times).") do
|
121
|
+
options[:log_level] -= 1
|
87
122
|
end
|
88
123
|
|
89
|
-
opts.on("-
|
90
|
-
|
124
|
+
opts.on("-t", "--timeout [SECONDS]", Integer,
|
125
|
+
"Time in seconds before disconnecting inactive clients (0 to disable).",
|
126
|
+
"(default: #{options[:timeout]})") do |timeout|
|
127
|
+
options[:timeout] = timeout
|
91
128
|
end
|
92
129
|
|
93
130
|
opts.separator ""; opts.separator "Miscellaneous:"
|
@@ -112,21 +149,22 @@ module StarlingServer
|
|
112
149
|
setup_signal_traps
|
113
150
|
@process.write_pid_file
|
114
151
|
|
115
|
-
|
116
|
-
@
|
152
|
+
STDOUT.puts "Starting at #{options[:host]}:#{options[:port]}."
|
153
|
+
@server = StarlingServer::Base.new(options)
|
154
|
+
@server.run
|
117
155
|
|
118
156
|
@process.remove_pid_file
|
119
157
|
end
|
120
158
|
|
121
159
|
def drop_privileges
|
122
|
-
Process.euid = options[:user] if options[:user]
|
123
160
|
Process.egid = options[:group] if options[:group]
|
161
|
+
Process.euid = options[:user] if options[:user]
|
124
162
|
end
|
125
163
|
|
126
164
|
def shutdown
|
127
165
|
begin
|
128
166
|
STDOUT.puts "Shutting down."
|
129
|
-
|
167
|
+
StarlingServer::Base.logger.info "Shutting down."
|
130
168
|
@server.stop
|
131
169
|
rescue Object => e
|
132
170
|
STDERR.puts "There was an error shutting down: #{e}"
|
@@ -178,7 +216,7 @@ module StarlingServer
|
|
178
216
|
safefork and exit
|
179
217
|
|
180
218
|
unless sess_id = Process.setsid
|
181
|
-
raise "Couldn't
|
219
|
+
raise "Couldn't detach from controlling terminal."
|
182
220
|
end
|
183
221
|
|
184
222
|
trap 'SIGHUP', 'IGNORE'
|
@@ -196,7 +234,7 @@ module StarlingServer
|
|
196
234
|
end
|
197
235
|
end
|
198
236
|
end
|
199
|
-
|
237
|
+
|
200
238
|
def redirect_io
|
201
239
|
begin; STDIN.reopen('/dev/null'); rescue Exception; end
|
202
240
|
|
@@ -205,7 +243,7 @@ module StarlingServer
|
|
205
243
|
STDOUT.reopen(@log_file, "a")
|
206
244
|
STDOUT.sync = true
|
207
245
|
rescue Exception
|
208
|
-
begin; STDOUT.reopen('/dev/null'); rescue Exception; end
|
246
|
+
begin; STDOUT.reopen('/dev/null'); rescue Exception; end
|
209
247
|
end
|
210
248
|
else
|
211
249
|
begin; STDOUT.reopen('/dev/null'); rescue Exception; end
|
@@ -224,6 +262,7 @@ module StarlingServer
|
|
224
262
|
|
225
263
|
def write_pid_file
|
226
264
|
return unless @pid_file
|
265
|
+
FileUtils.mkdir_p(File.dirname(@pid_file))
|
227
266
|
File.open(@pid_file, "w") { |f| f.write(Process.pid) }
|
228
267
|
File.chmod(0644, @pid_file)
|
229
268
|
end
|