Skip to content

Instantly share code, notes, and snippets.

@ahoward
Created March 10, 2011 18:45
Show Gist options
  • Save ahoward/864637 to your computer and use it in GitHub Desktop.
Save ahoward/864637 to your computer and use it in GitHub Desktop.
# a daemon method that blocks until the grandchild is ready
#
# sending the pid up a pipe (grandchild -> child -> parent)
#
def daemon(options = {}, &block)
# setup
#
raise(ArgumentError, 'no block!') unless block
chdir = options[:chdir] || options['chdir'] || '.'
umask = options[:umask] || options['umask'] || 0
# setup pipes we'll use for IPC
#
ra, wa = IO.pipe
rb, wb = IO.pipe
pid = fork
parent = !!pid
child = !parent
# in the parent we wait for the child to send back the grandchild's pid
#
if parent
at_exit{ exit! }
wa.close
r = ra
rb.close
w = wb
pid = r.gets
w.puts(pid)
return Integer(pid.strip)
end
# in the child start a grandchild. handshake the pid with the parent.
#
if child
ra.close
w = wa
wb.close
r = rb
open("/dev/null", "r+") do |fd|
STDIN.reopen(fd)
STDOUT.reopen(fd)
STDERR.reopen(fd)
end
Process::setsid rescue nil
pid =
fork do
Dir::chdir(chdir)
File::umask(umask)
$DAEMON = true
block.call()
exit!
end
w.puts(pid)
r.gets
exit!
end
end
if $0 == __FILE__
pid =
daemon do
'this code runs in a grandchild...'
end
STDERR.puts "parent says #{ pid }..."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment