On 12.12.2009 10:53, Iki Baz Castillo wrote:
> El Sado, 12 de Diciembre de 2009, David Masover escribi
>> On Friday 11 December 2009 05:33:06 pm Iki Baz Castillo wrote:
>>> The good point of using:
>>>
>>>   start-stop-daemon --stop --pidfile /var/run/rb_program.pid --name
>>>  rb_program
>>>
>>> is that it would stop the process just if it's called "rb_program" and
>>> its pid matches the value of /var/run/rb_program.pid, so you cannot kill
>>> any other process using that pid by accident (it could occur if your
>>> program didn't delete the pidfile and a new process has taken same pid
>>> value).
>> That's a good point -- though I would guess that in theory, it shouldn't be
>> possible for a program to die in such a way that it wouldn't be able to
>>  delete that file. The only thing that would make sense is a reboot, and on
>>  my system, /var/run is a tmpfs (only exists in RAM/swap), so it's not>  stored anywhere that would survive a reboot.
> 
> Well, usually daemons are coded to deelte the pidfile upon receipt of aIGINT 
> signal (or some others). But if the daemon is killed with "kill -9 PID"hen 
> it terminates inmediately without deleting the piddile.
> 
> In the case of a crash or segmentfault the daemon wouldn't delete the pidfile 
> again.
> 
> I've coded my Debian init script "start" action so it deletes the existing 
> "pidfile" if it exists (it shouldn't).

You can make deletion conditionally depending on the presence of the 
process (kill 0).  This is what I would do:

VAR='/var/run'

pid_file = File.join(VAR, File.basename($0) + '.pid')

begin
   old_pid = File.read(pid_file).to_i
   Process.kill 0, old_pid
   $stderr.puts "ERROR: already running with PID #{old_pid}"
   exit 1
rescue Errno::ENOENT
   # no pid file
rescue Errno::ESRCH
   # process not running
   $stderr.puts 'WARNING: stale pid file'
end

# open file with EXCL in order to catch race conditions where two
# processes were started almost at the same time and both thought
# they would be a new instance.  Uncomment sleep to simulate:
# sleep 2
File.open(pid_file, File::EXCL | File::WRONLY | File::CREAT) {|io| 
io.write($$)}
trap(0) {File.delete pid_file}

puts "OK, here we go."

# just for testing purposes:
File.read(pid_file).to_i == $$ or raise "What went wrong?"

sleep 10

puts "Finished"


> Thanks a lot for all your suggestions, it's a really interesting subject.
> However I would prefer to keep the code as simple as possible. The only 
> wanted was the possibility of kill my program using "killall rb_program".

Why does it have to be "killall"?  What about providing a command line 
option "-k" or "--kill" for killing (e.g. as ssh-agent does)?  You could ntegrate that pretty easily with the PID handling code above.

> To summarize this is possible in these cases:
> 
> a) Hardcoding the ruby location (avoiding using "env").
> Not user-friendly.

I personally do not find it too unfriendly to place the interpreter name ith an absolute path in the script.  This has also greater safety and 
robustness: the one installing the program and ruby interpreter (some 
person with administrative permissions) is likely the same and can 
ensure location is set properly.  Relying on users' environments is more ragile IMHO.

> b) Creating a link "rb_program" to ruby interpreter and invoke my program with 
> "rb_program /PATH_TO_rb_program.rb".
> Not very beauty :)
> 
> c) Replacing env with your above suggestion.
> It involves compiling a C program, it could break something in a not pure 
> Linux environment...
> 
> Well, I've learnt *a lot* in this thread but at this point I think is better 
> just to leave the code as it is.
> Really thanks a lot.

Well, it's your choice.

Kind regards

	robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/