rubydaemons

Starting and Stopping Ruby Daemons


I'm trying to start and stop an infinite loop daemon using the daemons gem.

Looking at the home page, I tried (in irb):

require 'daemons'
=>true
task_handle = Daemons.call do
  loop{
    sleep 10
    puts "foo"
  }
end
=> #<Daemons::Application:0x000000043f96d0 ...
task_handle.stop
=> nil
task_handle2 = Daemons.call do
  loop{
    sleep 10
    puts "bar"
  }
end

=>Daemons::RuntimeException: there is already one or more instance(s) of the program running
from /home/bdares/.rvm/gems/ruby-1.9.3-p194/gems/daemons-1.1.9/lib/daemons/application_group.rb:125:in `new_application'
from /home/bdares/.rvm/gems/ruby-1.9.3-p194/gems/daemons-1.1.9/lib/daemons.rb:251:in `call'
from (irb):21

Now, the exact example (#3 on the linked page) I'm looking at makes the first call with the option :multiple => true, but I really only need one daemon to be running at a time (and multiple ones would, in fact, be undesirable).

Is the first daemon still somehow alive and not being GC'd? If so, what am I missing?


Solution

  • I think the misunderstanding here is that daemons do not run in order. By the nature of them, they run in parallel with very little coordination between them. I'm sure you could find Ruby interfaces to System V IPC semaphores to coordinate them, but if you want a job queue, look at something besides Daemons.

    Also, to add to @Sigurd's answer above, here's the code in question that implements the :force option (which is conveniently undocumented) (source):

    115: if @applications.size > 0 and not @multiple
    116:         if options[:force]
    117:           @applications.delete_if {|a|
    118:             unless a.running?
    119:               a.zap
    120:               true
    121:             end
    122:           }
    123:         end
    124:         
    125:         raise RuntimeException.new('there is already one or more instance(s) of the program running') unless @applications.empty?
    126:       end
    

    So basically, (zap, as I found in the source, does absolutely nothing), when you specify :force, Daemons will delete all non-running applications from @applications if multiple isn't set. Otherwise, you get an error. So what that means is that if you don't specify :force or :multiple, your on a one way street to errors.

    Note: The reason for all of this is that Application#stop doesn't remove the Daemon from the ApplicationGroup (which is in charge of creating new jobs).

    Note: By the way, it's bad form in Ruby to use {} for multiline blocks. Use {} only for single line blocks. Use do...end for multiline instead.