module Daemonizable

module Daemonizable requires that the including class defines the @pid_file instance variable

Public Instance Methods

daemonize(argv, name, stdout_file = nil) { || ... } click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 29
def daemonize(argv, name, stdout_file = nil)
  remove_stale_pid_file
  pwd = Dir.pwd

  if RaadTotem.jruby?
    # in jruby the process is to posix-spawn a new process and re execute ourself using Spoon.
    # swap command 'start' for 'post_fork' to signal the second exec
    spanw_options = [RaadTotem.ruby_path].concat(RaadTotem.ruby_options)
    spanw_options << $0
    spanw_options.concat(argv.map{|arg| arg == 'start' ? 'post_fork' : arg})
    Spoon.spawnp(*spanw_options)
  else
    # do the double fork dance
    Process.fork do
      Process.setsid
      exit if fork # exit parent

      Dir.chdir(pwd)
      post_fork_setup(name, stdout_file)

      yield
    end
  end
end
force_kill_and_remove_pid_file(pid) click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 92
def force_kill_and_remove_pid_file(pid)
  puts(">> sending KILL signal to process #{pid}")
  Process.kill("KILL", pid)
  remove_pid_file
  true
rescue Errno::ESRCH # No such process
  puts(">> can't send KILL, no such process #{pid}")
  remove_pid_file
  false
end
pid() click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 25
def pid
  File.exist?(@pid_file) ? open(@pid_file).read.to_i : nil
end
post_fork_setup(name, stdout_file = nil) click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 54
def post_fork_setup(name, stdout_file = nil)
  $0 = name # set process name, does not work with jruby

  File.umask(0000) # file mode creation mask to 000 to allow creation of files with any required permission late
  write_pid_file

  # redirect stdin, stdout, stderr
  STDIN.reopen('/dev/null')
  stdout_file ? STDOUT.reopen(stdout_file, "a") : STDOUT.reopen('/dev/null', 'a')
  STDERR.reopen(STDOUT)

  at_exit do
    remove_pid_file
  end
end
read_pid_file() click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 103
def read_pid_file
  if File.file?(@pid_file) && pid = File.read(@pid_file)
    pid.to_i
  else
    nil
  end
end
remove_pid_file() click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 111
def remove_pid_file
  File.delete(@pid_file) if @pid_file && File.exists?(@pid_file)
end
remove_stale_pid_file() click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 120
def remove_stale_pid_file
  if File.exist?(@pid_file)
    if pid && Process.running?(pid)
      raise PidFileExist, "#{@pid_file} exists and process #{pid} is runnig. stop the process or delete #{@pid_file}"
    else
      puts(">> deleting stale pid file #{@pid_file}")
      remove_pid_file
    end
  end
end
send_signal(signal, timeout = 60) click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 70
def send_signal(signal, timeout = 60)
  if pid = read_pid_file
    puts(">> sending #{signal} signal to process #{pid}")
    Process.kill(signal, pid)
    Timeout.timeout(timeout) do
      sleep 0.1 while Process.running?(pid)
    end
    true
  else
    puts(">> can't stop process, no pid found in #{@pid_file}")
    false
  end
rescue Timeout::Error
  force_kill_and_remove_pid_file(pid)
rescue Interrupt
  force_kill_and_remove_pid_file(pid)
rescue Errno::ESRCH # No such process
  puts(">> can't stop process, no such process #{pid}")
  remove_pid_file
  false
end
write_pid_file() click to toggle source
# File lib/raad_totem/unix_daemon.rb, line 115
def write_pid_file
  open(@pid_file,"w") { |f| f.write(Process.pid) }
  File.chmod(0644, @pid_file)
end