Question

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?

Was it helpful?

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.

OTHER TIPS

The following code would work fine:

require 'daemons'
task_handle = Daemons.call(:force => true)  do
  loop{
    sleep 10
    puts "foo"
  }
end

task_handle.stop

task_handle2 = Daemons.call do
  loop{
    sleep 10
    puts "foo"
  }
end

The change is in a first call :force option. Daemons check app number that were created, not just that they are running. In your case, even after stop the first instance still exists. The "force" option cleans applications that are not running.

Please note that you may get another problem - task_handle.stop does not guarantee that the spawned proc would be stopped immediately, so you need to handle that situation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top