Permalink
Browse files

Skynet manager now supports being daemonized by running ./script/skyn…

…et start and ./script/skynet stop!
  • Loading branch information...
1 parent 3e4be9c commit 13ac39c546f82e688a7b88018a2702542c114c62 phlapjack committed May 2, 2008
Showing with 72 additions and 16 deletions.
  1. +1 −0 History.txt
  2. +12 −1 lib/skynet.rb
  3. +6 −1 lib/skynet/skynet_launcher.rb
  4. +53 −14 lib/skynet/skynet_manager.rb
View
@@ -1,4 +1,5 @@
== 0.9.3 2008-04-10
+ - Support starting Skynet with ./script/skynet start and stop to daemonize
- Close file handles on exec.
Skynet::Worker and Skynet::Manager now call Skynet.fork_and_exec instead of their own versions.
Skynet.fork_and_exec prevents file descriptor exhaustion by calling Skynet.close_file_handles.
View
@@ -54,14 +54,25 @@ def self.fork_and_exec(command)
sleep 0.01 # remove contention on manager drb object
log = Skynet::Logger.get
info "executing /bin/sh -c \"#{command}\""
- pid = fork do
+ pid = safefork do
close_files
exec("/bin/sh -c \"#{command}\"")
exit
end
Process.detach(pid)
pid
end
+
+ def self.safefork (&block)
+ @fork_tries ||= 0
+ fork(&block)
+ rescue Errno::EWOULDBLOCK
+ raise if @fork_tries >= 20
+ @fork_tries += 1
+ sleep 5
+ retry
+ end
+
# close open file descriptors starting with STDERR+1
def self.close_files(from=3, to=50)
@@ -10,8 +10,13 @@ def self.start(options={})
else
if Skynet::CONFIG[:SKYNET_LOG_DIR] == Skynet::DEFAULT_LOG_FILE_LOCATION
puts "Logging to the default log: #{File.expand_path(Skynet::CONFIG[:SKYNET_LOG_FILE])}. Set Skynet::CONFIG[:SKYNET_LOG_FILE] to change.\nYou will no longer see this warning once the Skynet::CONFIG[:SKYNET_LOG_FILE] is set."
+ end
+ if ARGV.include?('stop')
+ Skynet::Manager.stop(options)
+ else
+ options["daemonize"] = true if ARGV.include?('start')
+ Skynet::Manager.start(options)
end
- Skynet::Manager.start(options)
end
end
@@ -185,14 +185,10 @@ def worker_shutdown
end
def worker_alive?(worker_pid)
- begin
- IO.popen("ps -o pid,command -p #{worker_pid}", "r") do |ps|
- return ps.detect {|line| line =~ /worker_type/}
- end
- rescue Errno::ENOENT => e
- return false
- end
- false
+ Process.kill(0,worker_pid)
+ return true
+ rescue Errno::ESRCH => e
+ return false
end
@@ -483,6 +479,11 @@ def self.start(options={})
opt.banner = %{Usage:
> skynet [options]
+ OR to daemonize
+
+ > skynet [options] start
+ > skynet stop
+
You can also run:
> skynet console [options]
}
@@ -582,24 +583,62 @@ def self.start(options={})
debug "CONTINUING TO START : There IS an available MessageQueue", options
# create main pid file
- File.open(options[:pid_file], 'w') do |file|
- file.puts($$)
- end
begin
printlog "STARTING THE MANAGER!!!!!!!!!!!"
@manager = Skynet::Manager.new(options)
DRb.start_service(Skynet::CONFIG[:SKYNET_LOCAL_MANAGER_URL], @manager)
- info "WORKER MANAGER URI: #{DRb.uri}"
@manager.start_workers
- @manager.run
- DRb.thread.join
+ if options["daemonize"]
+ Skynet.safefork do
+ sess_id = Process.setsid
+ Skynet.close_console
+ run_manager(@manager)
+ end
+ else
+ run_manager(@manager)
+ end
rescue SystemExit, Interrupt
rescue Exception => e
fatal("Error in Manager. Manager Dying. #{e.inspect} #{e.backtrace}")
end
end
end
+
+ def self.run_manager(manager)
+ write_pid_file
+ info "WORKER MANAGER URI: #{DRb.uri}"
+ manager.run
+ DRb.thread.join
+ end
+
+ # stop the daemon, nicely at first, and then forcefully if necessary
+ def self.stop(options = {})
+ pid = read_pid_file
+ raise "The Skynet Manager is not running" unless pid
+ $stdout.puts "Stopping Skynet"
+ printlog "Stopping Skynet"
+ Process.kill("TERM", pid)
+ 180.times { Process.kill(0, pid); sleep(1) }
+ $stdout.puts("using kill -9 #{pid}")
+ Process.kill(9, pid)
+ rescue Errno::ESRCH => e
+ $stdout.puts "process #{pid} has stopped"
+ printlog "Skynet Stopped"
+ ensure
+ File.unlink(Skynet::Config.pidfile_location) if File.exist?(Skynet::Config.pidfile_location)
+ end
+
+ def self.read_pid_file
+ pidfile = Skynet::Config.pidfile_location
+ File.read(pidfile).to_i if File.exist?(pidfile)
+ end
+
+ def self.write_pid_file
+ pidfile = Skynet::Config.pidfile_location
+ open(pidfile, "w") {|f| f << Process.pid << "\n"}
+ at_exit { File.unlink(pidfile) if read_pid_file == Process.pid }
+ end
end
end

0 comments on commit 13ac39c

Please sign in to comment.