module Daemonize

def call_as_daemon(block, logfile_name = nil, app_name = nil)

def call_as_daemon(block, logfile_name = nil, app_name = nil)
  rd, wr = IO.pipe
  
  if tmppid = safefork
    # parent
    wr.close
    pid = rd.read.to_i
    rd.close
    
    Process.waitpid(tmppid)
    
    return pid
  else
    # child
    
    rd.close
    
    # Detach from the controlling terminal
    unless sess_id = Process.setsid
      raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
    end

    # Prevent the possibility of acquiring a controlling terminal
    #if oldmode.zero?
      trap 'SIGHUP', 'IGNORE'
      exit if pid = safefork
    #end

    wr.write Process.pid
    wr.close
    
    $0 = app_name if app_name
    
    Dir.chdir "/"   # Release old working directory
    File.umask 0000 # Insure sensible umask

    # Make sure all file descriptors are closed
    ObjectSpace.each_object(IO) do |io|
      unless [STDIN, STDOUT, STDERR].include?(io)
        begin
          unless io.closed?
            io.close
          end
        rescue ::Exception
        end
      end
    end
    
    ios = Array.new(8192){|i| IO.for_fd(i) rescue nil}.compact
    ios.each do |io|
      next if io.fileno < 3
      io.close
    end

    redirect_io(logfile_name)  
  
    block.call
    
    exit
  end
end

def daemonize(logfile_name = nil, app_name = nil)

This method causes the current running process to become a daemon
def daemonize(logfile_name = nil, app_name = nil)
  srand # Split rand streams between spawning and daemonized process
  safefork and exit # Fork and exit from the parent
  # Detach from the controlling terminal
  unless sess_id = Process.setsid
    raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
  end
  # Prevent the possibility of acquiring a controlling terminal
  #if oldmode.zero?
    trap 'SIGHUP', 'IGNORE'
    exit if pid = safefork
  #end
  $0 = app_name if app_name
  
  Dir.chdir "/"   # Release old working directory
  File.umask 0000 # Insure sensible umask
  # Make sure all file descriptors are closed
  ObjectSpace.each_object(IO) do |io|
    unless [STDIN, STDOUT, STDERR].include?(io)
      begin
        unless io.closed?
          io.close
        end
      rescue ::Exception
      end
    end
  end
  redirect_io(logfile_name)
  
  #return oldmode ? sess_id : 0   # Return value is mostly irrelevant
  return sess_id
end

def redirect_io(logfile_name)

STDOUT/STDERR should go to a logfile
point them somewhere sensible
Free file descriptors and
def redirect_io(logfile_name)
  begin; STDIN.reopen "/dev/null"; rescue ::Exception; end       
   
  if logfile_name
    begin
      STDOUT.reopen logfile_name, "a" 
      File.chmod(0644, logfile_name)
      STDOUT.sync = true
    rescue ::Exception
      begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
    end
  else
    begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
  end
  
  begin; STDERR.reopen STDOUT; rescue ::Exception; end
  STDERR.sync = true
end

def safefork

maximum process limit for the system has been reached
Try to fork if at all possible retrying every 5 sec if the
def safefork
  tryagain = true
  while tryagain
    tryagain = false
    begin
      if pid = fork
        return pid
      end
    rescue Errno::EWOULDBLOCK
      sleep 5
      tryagain = true
    end
  end
end

def simulate(logfile_name = nil)

def simulate(logfile_name = nil)
  # NOTE: STDOUT and STDERR will not be redirected to the logfile, because in :ontop mode, we normally want to see the output
  
  Dir.chdir "/"   # Release old working directory
  File.umask 0000 # Insure sensible umask
  # Make sure all file descriptors are closed
  ObjectSpace.each_object(IO) do |io|
    unless [STDIN, STDOUT, STDERR].include?(io)
      begin
        unless io.closed?
          io.close
        end
      rescue ::Exception
      end
    end
  end
  # Free file descriptors and
  # point them somewhere sensible
  # STDOUT/STDERR should go to a logfile
  
  begin; STDIN.reopen "/dev/null"; rescue ::Exception; end       
end