Proper way to daemonize

module Process
  def self.daemon( nochdir = nil, noclose = nil )
    exit if fork # Parent exits, child continues.
    Process.setsid # Become session leader.
    exit if fork # Zap session leader.

    unless nochdir
      Dir.chdir "/" # Release old working directory.
    end

    File.umask 0000 # Ensure sensible umask. Adjust as needed.

    unless noclose
      STDIN.reopen "/dev/null" # Free file descriptors and
      STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
      STDERR.reopen '/dev/null', 'a'
    end

    return 0
  end
end

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.
Instead, "exit!" should be used to prevent "at_exit" handlers from
being called.

Any thoughts about this subtle change? Are there any undesirable side
effects that arise from using exit! instead of exit ?

Blessings,
TwP

What resources are you talking about? By the time exit is called, the
process has already been duplicated. The child process won't be affected
by anything the parent does during via at_exit processing (at least
with respect to Ruby object resources).

···

On Apr 24, 2009, at 11:11 AM, Tim Pease wrote:

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.

Why not just:

require 'webrick/server'

WEBrick::Dameon.start

It has exit! and all that built-in.

···

On Apr 24, 2009, at 08:11, Tim Pease wrote:

# ...

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.
Instead, "exit!" should be used to prevent "at_exit" handlers from
being called.

Any thoughts about this subtle change? Are there any undesirable side
effects that arise from using exit! instead of exit ?

But if that at_exit() handler deletes a file or something…

Anyway, I do use exit!() in my daemonize() method.

James Edward Gray II

···

On Apr 24, 2009, at 11:01 AM, Gary Wright wrote:

On Apr 24, 2009, at 11:11 AM, Tim Pease wrote:

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.

What resources are you talking about? By the time exit is called, the
process has already been duplicated. The child process won't be affected
by anything the parent does during via at_exit processing (at least
with respect to Ruby object resources).

Eric, if I had half your brain I'd be twice as smart. Didn't even
think to look through the stdlibs.

Sinatra and Rails use the plain old "exit" in their flavor of the
daemon method. This is causing issues with closing out log files
prematurely. Just getting a consensus from the wider ruby community
about the _correct_ behavior.

Blessings,
TwP

···

On Fri, Apr 24, 2009 at 12:46 PM, Eric Hodel <drbrain@segment7.net> wrote:

On Apr 24, 2009, at 08:11, Tim Pease wrote:

# ...

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.
Instead, "exit!" should be used to prevent "at_exit" handlers from
being called.

Any thoughts about this subtle change? Are there any undesirable side
effects that arise from using exit! instead of exit ?

Why not just:

require 'webrick/server'

WEBrick::Dameon.start

It has exit! and all that built-in.

Well, that is why I put the caveat about 'Ruby object resources'.
Isn't it fair to assume the at_exit code isn't actively hostile? :slight_smile:

If you've got at_exit() code that is trashing external resources that are used by a child process, that is a bug to be fixed I think rather than a bug to be obscured via exit!

···

On Apr 24, 2009, at 12:11 PM, James Gray wrote:

On Apr 24, 2009, at 11:01 AM, Gary Wright wrote:

On Apr 24, 2009, at 11:11 AM, Tim Pease wrote:

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.

What resources are you talking about? By the time exit is called, the
process has already been duplicated. The child process won't be affected
by anything the parent does during via at_exit processing (at least
with respect to Ruby object resources).

But if that at_exit() handler deletes a file or something…

As of Ruby 1.9 Process.daemon() is a core method. Just one more reason 1.9 rocks. :slight_smile:

James Edward Gray II

···

On Apr 24, 2009, at 2:07 PM, Tim Pease wrote:

On Fri, Apr 24, 2009 at 12:46 PM, Eric Hodel <drbrain@segment7.net> > wrote:

On Apr 24, 2009, at 08:11, Tim Pease wrote:

# ...

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.
Instead, "exit!" should be used to prevent "at_exit" handlers from
being called.

Any thoughts about this subtle change? Are there any undesirable side
effects that arise from using exit! instead of exit ?

Why not just:

require 'webrick/server'

WEBrick::Dameon.start

It has exit! and all that built-in.

Eric, if I had half your brain I'd be twice as smart. Didn't even
think to look through the stdlibs.

Yes, I am using an at_exit hook to close out file descriptors used by
loggers. Part of this close out process is writing out some diagnostic
messages to the loggers. These at_exit hooks need to be called when
the child process exits, not when the parent process exits.

The two solutions are:

1) daemonize is the VERY FIRST thing the program should do before any
initialization is run
2) daemonize should use exit! if initialization needs to be performed
before daemonizing

Anyway, it sounds like James is using exit! without ill affect. /me
heads in that direction.

Blessings,
TwP

···

On Fri, Apr 24, 2009 at 10:40 AM, Gary Wright <gwtmp01@mac.com> wrote:

On Apr 24, 2009, at 12:11 PM, James Gray wrote:

On Apr 24, 2009, at 11:01 AM, Gary Wright wrote:

On Apr 24, 2009, at 11:11 AM, Tim Pease wrote:

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.

What resources are you talking about? By the time exit is called, the
process has already been duplicated. The child process won't be affected
by anything the parent does during via at_exit processing (at least
with respect to Ruby object resources).

But if that at_exit() handler deletes a file or something…

Well, that is why I put the caveat about 'Ruby object resources'.
Isn't it fair to assume the at_exit code isn't actively hostile? :slight_smile:

If you've got at_exit() code that is trashing external resources that are
used by a child process, that is a bug to be fixed I think rather than a bug
to be obscured via exit!

Well, that is why I put the caveat about 'Ruby object resources'.
Isn't it fair to assume the at_exit code isn't actively hostile? :slight_smile:

Well I do see the smiley but still want to point out that "passively
hostile" might be bad enough, actually pretty bad!

If you've got at_exit() code that is trashing external resources that are
used by a child process, that is a bug to be fixed I think rather than a bug
to be obscured via exit!

This is a good point though, I guess bombing in the child might indeed
be the best way to find out what is conceptually wrong, but I am quite
unexperienced with this kind of code in Ruby. OTOH are not most of us?

Cheers
Robert

···

On Fri, Apr 24, 2009 at 6:40 PM, Gary Wright <gwtmp01@mac.com> wrote:

--
Si tu veux construire un bateau ...
Ne rassemble pas des hommes pour aller chercher du bois, préparer des
outils, répartir les tâches, alléger le travail… mais enseigne aux
gens la nostalgie de l’infini de la mer.

If you want to build a ship, don’t herd people together to collect
wood and don’t assign them tasks and work, but rather teach them to
long for the endless immensity of the sea.

--
Antoine de Saint-Exupéry

Seems like Tim has a pretty decent example where the behavior doesn't feel buggy.

Basically, I view it this way. The exit() calls in a daemonize() method aren't the typical usage. Normally, exit() is used to end a process. Our process isn't really ending though so much as transitioning into a different kind of process. exit() is just an implementation detail of how that transition occurs. As such, exit!() feels more correct to me because I don't want to go through a shutdown sequence of the original process, I just want the first to immediately cease to exist while the second takes over for it.

That's all just my opinion though. Feel free to ignore.

James Edward Gray II

···

On Apr 24, 2009, at 11:40 AM, Gary Wright wrote:

On Apr 24, 2009, at 12:11 PM, James Gray wrote:

On Apr 24, 2009, at 11:01 AM, Gary Wright wrote:

On Apr 24, 2009, at 11:11 AM, Tim Pease wrote:

This is the standard code to daemonize a process. The use of "exit"
bothers me slightly, as it will call all "at_exit" handlers in the
parent. I do not believe this is the desired behavior; the "at_exit"
handlers will free resources that the daemonized process might need.

What resources are you talking about? By the time exit is called, the
process has already been duplicated. The child process won't be affected
by anything the parent does during via at_exit processing (at least
with respect to Ruby object resources).

But if that at_exit() handler deletes a file or something…

Well, that is why I put the caveat about 'Ruby object resources'.
Isn't it fair to assume the at_exit code isn't actively hostile? :slight_smile:

If you've got at_exit() code that is trashing external resources that are used by a child process, that is a bug to be fixed I think rather than a bug to be obscured via exit!

I wouldn't call it buggy, but calling at_exit in a process that shouldn't execute the block seems premature. Better to wait and call it in the forked child process, I think.

It looks like 1.9's Process.daemon uses exit! and it doesn't look like it does a double-fork which is a best-practice sort of thing (in order to avoid acquiring a new controlling terminal). I suppose I should open a ticket...

Gary Wright

···

On Apr 24, 2009, at 3:17 PM, James Gray wrote:

Seems like Tim has a pretty decent example where the behavior doesn't feel buggy.

It looks like 1.9's Process.daemon uses exit! and it doesn't look like
it does a double-fork which is a best-practice sort of thing (in order
to avoid acquiring a new controlling terminal). I suppose I should
open a ticket...

Gary Wright

Something like this perhaps?

  def RDaemon.daemon(&block)
    unless fork
      Process::setsid
      unless fork
        Dir::chdir('/')
  File::umask(0)
  STDIN.reopen("/dev/null")
  STDOUT.reopen("/dev/null", "a") unless $DEBUG
  STDERR.reopen("/dev/null", "a") unless $DEBUG
  loop do
          yield
        end
      end
    end
    exit!(0)
  end

···

--
Posted via http://www.ruby-forum.com/\.