starling 0.9.3 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|