Ruby/God/Dash and undead processes.

I have a god script that starts a process that I want to run.

My god config file contained:

God.watch do |w|
  w.name = "foobar"
  w.start = "rails runner 'SomeClass.SomeMethod'"
  ...
end

When god starts this, it starts TWO processes:

    sh -c rails runner "SomeClass.SomeMethod"

and
    rails runner "SomeClass.SomeMethod"

God keeps track of the pid for the `sh -c rails runner ...` process. When I tries to stop it, it sends a signal to the PID which stops the `sh -c ...` process but the other process remains running.

I made some tests and I discovered it's was (maybe?) ruby issue.

Consider this simple ruby script:

    # t.rb
    loop do
        sleep 1
    end

If I run it like this:

    sh -c "ruby t.rb" &

It starts two processes:

    $ ps awux | grep ruby
    user      4587  0.0  0.1   2216   540 pts/0    S    13:13   0:00 sh -c ruby t.rb
    user      4588  1.0  0.7   8888  3560 pts/0    Sl   13:13   0:00 ruby t.rb

When I try to kill the sh process in the hope that the ruby process dies too, I was disappointed. Only the sh process died.

I was not satisfied with my theory so I tried with perl, php and another bash script. ALL did the same thing!

It's not a ruby thing after all!!

So, instead of using sh I tried using bash:

    bash -c "ruby t.rb" &

SURPRISE!!! killing the bash process actually killed the ruby process too!!

I found out that "sh" was in reality dash. It is my understanding that dash is POSIX and therefor cross-platform compatible. That is probably why GOD was using it.

I decided to go back to school and run:

man dash

I did not read it all but I searched for process, background, kill, sub-process, etc...

Eventually, I ended up reading about "exec". Of course!!!! I told myself.

exec [command arg ...]
Unless command is omitted, the shell process is replaced with the specified program (which must be a real
program, not a shell builtin or function). Any redirections on the exec command are marked as permanent,
so that they are not undone when the exec command finishes.

I decided to test this...

    $ sh -c "exec ruby t.rb" &
    $ ps awux | grep ruby
    user      4588  1.0  0.7   8888  3560 pts/0    Sl   13:13   0:00 ruby t.rb
    $ kill $!

Marvelous! It worked! Only ONE process, not two! When I kill that process, it dies, naturally!

So, in my god config file I used:

w.start="exec rails runner 'SomeClass.SomeMethod'"

and VOILA!

Thanks a million

Was on the verge of using a pid file, you saved us hours of unneeded work

Any idea? When I put

Any idea? When I put w.start="exec rails runner....."

gems/god-0.13.1/lib/god/process.rb:324:in `exec': No such file or directory - exec rails runner -e development RunMethod.new

Using Ubuntu?

Rylan,

I suppose you are not using Ubuntu?
The command `exec` is a builtin command inside bash and inside dash.
In my environment, I am using Ubuntu and /bin/sh is linked to dash which is what god uses.

I hope that helps

--
Christian Roy

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote>
  • You may post PHP code. You should include <?php ?> tags.
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]". PHP source code can also be enclosed in <?php ... ?> or <% ... %>.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options