Forum: Ruby proper way to daemonize

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
4d5b5dd4e263d780a5dfe7ac8b8ac98c?d=identicon&s=25 Tim Pease (Guest)
on 2009-04-24 17:15
(Received via mailing list)
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
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2009-04-24 18:03
(Received via mailing list)
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).
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2009-04-24 18:12
(Received via mailing list)
On Apr 24, 2009, at 11:01 AM, Gary Wright wrote:

> 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…

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

James Edward Gray II
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2009-04-24 18:41
(Received via mailing list)
On Apr 24, 2009, at 12:11 PM, James Gray wrote:

>> 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? :-)

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!
4d5b5dd4e263d780a5dfe7ac8b8ac98c?d=identicon&s=25 Tim Pease (Guest)
on 2009-04-24 19:20
(Received via mailing list)
On Fri, Apr 24, 2009 at 10:40 AM, Gary Wright <gwtmp01@mac.com> wrote:
>>>> handlers will free resources that the daemonized process might need.
> Isn't it fair to assume the at_exit code isn't actively hostile? :-)
>
> 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!
>

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
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2009-04-24 20:45
(Received via mailing list)
On Fri, Apr 24, 2009 at 6:40 PM, Gary Wright <gwtmp01@mac.com> wrote:

> 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? :-)
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



--
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.
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 Eric Hodel (Guest)
on 2009-04-24 20:47
(Received via mailing list)
On Apr 24, 2009, at 08:11, Tim Pease wrote:
> 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.
4d5b5dd4e263d780a5dfe7ac8b8ac98c?d=identicon&s=25 Tim Pease (Guest)
on 2009-04-24 21:09
(Received via mailing list)
On Fri, Apr 24, 2009 at 12:46 PM, Eric Hodel <drbrain@segment7.net>
wrote:
>>
>
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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2009-04-24 21:12
(Received via mailing list)
On Apr 24, 2009, at 2:07 PM, Tim Pease wrote:

>>> Instead, "exit!" should be used to prevent "at_exit" handlers from
>> 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.

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

James Edward Gray II
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2009-04-24 21:18
(Received via mailing list)
On Apr 24, 2009, at 11:40 AM, Gary Wright wrote:
>>>> parent. I do not believe this is the desired behavior; the
>>
>> 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? :-)
>
> 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!

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
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2009-04-25 00:54
(Received via mailing list)
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.

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
C1b6b5557723c9db912b075e954166d3?d=identicon&s=25 Jeff Moore (djief)
on 2009-04-25 02:54
>
> 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
This topic is locked and can not be replied to.