なるほどUnixプロセス ― Rubyで学ぶUnixの基礎

なるほどUnixプロセス ― Rubyで学ぶUnixの基礎
Jesse Storimer, 島田浩二(翻訳), 角谷信太郎(翻訳)
達人出版会
発行日: 2013-04-25
対応フォーマット: EPUB, PDF, ZIP

まだβ版ですが、面白そうだったので買ってみました。初代iPadiBooks上で全152ページで値段が2,980(正式には3,360)円というのはちと高い気がしますが、原書が$27なのでまあしょうがないでしょう。

で、ざざっと読んでみた感想としては面白いですね。Unixのプロセスの話をRubyで学ぶようになっていてC言語でやるよりはRubyの方が抽象度が高いので比較的わかりやすいと思います。類書も無いような気がしますね。

シグナルのあたりとかパラパラと読んでいて、そういやfluentdだとどうなってんだっけと思いsupervisor.rbを読んでみました。

startメソッドはこんな感じになっています。fluentdを起動するとここが呼ばれます。

  def start
    require 'fluent/load'
    @log.init

    start_daemonize if @daemonize
    install_supervisor_signal_handlers
    until @finished
      supervise do
        read_config
        change_privilege
        init_engine
        install_main_process_signal_handlers
        run_configure
        finish_daemonize if @daemonize
        run_engine
        exit 0
      end
    end
  end

fluentdを起動するとsupervisorプロセスとその子プロセスであるワーカープロセス(メインプロセス)の2つのプロセスが起動します。

$ pgrep -f fluentd

とやると2つのプロセスのプロセスIDを表示することができます。

supervisorプロセスにシグナルハンドラを登録しているのがinstall_supervisor_signal_handlersメソッドです。

  def install_supervisor_signal_handlers
    trap :INT do
      @finished = true
      if pid = @main_pid
        Process.kill(:INT, pid)
      end
    end

    trap :TERM do
      @finished = true
      if pid = @main_pid
        Process.kill(:TERM, pid)
      end
    end

    trap :HUP do
      $log.info "restarting"
      if pid = @main_pid
        Process.kill(:TERM, pid)
      end
    end

    trap :USR1 do
      @log.reopen!
      if pid = @main_pid
        Process.kill(:USR1, pid)
      end
    end
  end

メインプロセスにシグナルハンドラを登録しているのはinstall_main_process_signal_handlersメソッドです。

  def install_main_process_signal_handlers
    trap :INT do
      Fluent::Engine.stop
    end

    trap :TERM do
      Fluent::Engine.stop
    end

    trap :HUP do
      # TODO
    end

    trap :USR1 do
      $log.info "force flushing buffered events"
      @log.reopen!
      Fluent::Engine.flush!
    end
  end

INTやTERMの場合はfluentdがstopします。

pkill -INT -f fluentd

とかやってみると確認できます。

一方で

pkill -HUP -f fluentd

とやるとfluentdが再起動します。
INT, TERMと違って@finishedがfalseのままなのでメインプロセスをkillしてもstartメソッド内のループは終了しないからですね。

pkill -USR1 -f fluentd

だとbufferをflushします。

詳細は本家のドキュメントを見るといいと思います。

Fluentd’s Signal Handling | Fluentd

ソースコードリーディングにはこちらが参考になると思います。
fluentd のソースを読む (1) - @kyanny's blog