module ActsAsFerret module Server # methods for becoming a daemon on Unix-like operating systems module UnixDaemon ################################################################################ def platform_daemon (&block) safefork do write_pid_file trap("TERM") { exit(0) } sess_id = Process.setsid STDIN.reopen("/dev/null") STDOUT.reopen("#{Rails.root}/log/ferret_server.out", "a") STDERR.reopen(STDOUT) block.call end end ################################################################################ # stop the daemon, nicely at first, and then forcefully if necessary def stop pid = read_pid_file raise "ferret_server doesn't appear to be running" unless pid $stdout.puts("stopping ferret server...") Process.kill("TERM", pid) 30.times { Process.kill(0, pid); sleep(0.5) } $stdout.puts("using kill -9 #{pid}") Process.kill(9, pid) rescue Errno::ESRCH => e $stdout.puts("process #{pid} has stopped") ensure File.unlink(@cfg.pid_file) if File.exist?(@cfg.pid_file) end ################################################################################ def safefork (&block) @fork_tries ||= 0 fork(&block) rescue Errno::EWOULDBLOCK raise if @fork_tries >= 20 @fork_tries += 1 sleep 5 retry end ################################################################################# # create the PID file and install an at_exit handler def write_pid_file ensure_stopped open(@cfg.pid_file, "w") {|f| f << Process.pid << "\n"} at_exit { File.unlink(@cfg.pid_file) if read_pid_file == Process.pid } end ################################################################################# def read_pid_file File.read(@cfg.pid_file).to_i if File.exist?(@cfg.pid_file) end ################################################################################# def ensure_stopped if pid = read_pid_file if process_exists(pid) raise "ferret_server may already be running, a pid file exists: #{@cfg.pid_file} and a ferret_server process exists with matching pid #{pid}" else $stdout.puts("removing stale pid file...") File.unlink(@cfg.pid_file) if File.exist?(@cfg.pid_file) end end end ################################################################################# # Check for existence of ferret_server process with PID from pid file # checked on ubuntu and OSX only def process_exists(pid) ps = IO.popen("ps -fp #{pid}", "r") process = ps.to_a[1] ps.close process =~ /ferret_server/ end end end end