2012-05-05

cline-0.3.0

いくつか便利そうな機能をつけてアップデートしました。

  • 簡単にURLを開く機能
  • フィルタリングのためのインターフェース

簡単にURLを開く

表示するときにメッセージにエイリアスをつけるようにしました。 その分、あまり必要なさそうな時間の秒とタイムゾーンを表示しないようにしました。

[2012/05/04 22:41][2][1f5] Delicious.com - Discover Yourself! http://delicious.com/help/quicktour/chrome
                       ↑
                      これ

エイリアスを使うと簡単にメッセージの中のURLをブラウザで開くことができます。 URLが途中で見切れてしまっても大丈夫。

  $ cline open 1f5

打つのが面倒なので alias co='cline open' しておくとよさそう。

フィルタリング

フィルタリングのようなことを、ActiveRecordのvalidationを使って実現できるようにしておきました。 invalidなメッセージは保存されなくなります。 ~/.cline/config あたりに書いておくとよさそう。

require 'hiwai'

class Cline::Notification
  validate :message_should_not_be_hiwai

  def message_should_not_be_hiwai
    errors.add :message, 'hiwai' if message.hiwai?
  end
end

クラスを再オープンしているのだけど、もうちょっとスマートなAPIを用意したいなと思っているところ。 ちなみにhiwaiはレシーバがひわいかどうかを確認するためのライブラリです。

2012-04-11

標準添付ライブラリもエディタで開けるreditorを作った

Rubyにはbundle openやgemeditのgem editみたいに、gemを自分のエディタで簡単に開くための方法があるのだけど、たまに標準添付ライブラリも開きたいことがあるのだった。 そこでreditorというgemを作ってみた。

インストールするとreditorコマンドが使えるようになって、開きたいライブラリの名前を渡すと$LOAD_PATHやrubygemsの中からそれっぽいものを見つけてエディタで開いてくれる。

  $ reditor csv

とか。

  $ reditor faraday

とか。

2012-03-29

所在の分からないWARNINGが出力されるときのこと

Railsを使ってるときとかにActiveSupport::MemoizableがDEPRECATEDだとかそんなWARNINGっぽいメッセージがどこからともなく出てくるときのこと。

ひとまずraiseする。IOで出力する系のメソッドたちはだいたい最後にwriteを呼ぶ筈なので、writeを上書きしてる。

def STDERR.write(*) raise end

Railsだとconfig/application.rbの頭あたりに書いておく。

起動してstacktraceを見ればどのgemが問題かだいたい分かるのでbundle update [gem name]で問題のgemをupdateしてみると直っていたりする。 最新でも直ってなかったら自分で直してpull requestを送ったりする。

2012-03-28

記号がうまく入力できない

感覚でキーボードを使うという悪癖が抜けないので、特に苦手な記号の入力を克服するべくコンソールで練習するためのプログラムを書くことにした。

kigou

ついでに実装は男らしい感じのコードにしようと思ったけどあまりうまくいかなくて、ただの汚いコードになった。

2012-03-26

プロセスをforkするときのこと

孤児プロセスとゾンビプロセスの違いがうまく理解できてなかったけど、ようやく違いを確認することができた。

孤児プロセス

孤児プロセスは、親プロセスがwaitせずに先に逝ってしまった後も走り続けている子プロセス。 Orphan Process とも呼ばれる。 親のいなくなった子プロセスはinitプロセスの子(孤児)になる。

親プロセスが死んで、子プロセスの親が変化する様子を見るには以下のようなスクリプトを実行したあとでファイルをtailすると分かりやすそう。

Process.fork do
  File.open('orphan', 'a') do |f|
    loop do
      sleep 1

      # 親プロセスのpidをファイルに書き出す
      f.puts Process.ppid
      f.flush
    end
  end
end

sleep 5

このプログラムを実行して、orphantail -fで観察していると、5秒後に親プロセスが死んで、子プロセスの親プロセスがinitに変化していることを確認できる。

$ tailf orphan
80361 # まだ親プロセスの子
80361
80361
80361
80361
1     # ここでinitの養子になってる
1
1
1

initは孤児プロセスをwaitしてくれる。

ゾンビプロセス

ゾンビプロセスは、既に処理を終えて死んだ子プロセスが、まだ生きている親プロセスにwaitされるのを待っている状態のこと。

子プロセスが死んでも親プロセスが生きている限り、いつ子プロセスの終了ステータスが参照されても(waitされても)いいように、その情報はプロセステーブルのエントリとして残る。 プロセスとしては死んでいるけれど、waitされるかもしれないのでプロセステーブルに残っている状態がゾンビ。

puts Process.fork { sleep 1 }

sleep 10

上のプログラムを実行して、表示されたpidを元に、別の端末でプロセスの状態を確認すると、ゾンビ状態になっていることがわかる(10秒後には親プロセスが死ぬのでゾンビも消える)。

$ ps -ho pid,state 81793
  PID STAT
  82077 Z+

ゾンビプロセスの発生を防ぐには、親プロセスで確実にwaitする必要がある。 RubyならProcess.waitpidを使うといい。 waitすると子プロセスが終了するまで親プロセスの処理がブロックされる。

pid = Process.fork { sleep 1 }

Process.waitpid pid

もしくは、Double Forkを行うと親プロセスで待たなくてもよくなる。 生成した子プロセスに孫プロセスを生成させ、さらに子プロセスは即座に終了させることで、孫プロセスがinitの子プロセス(孤児プロセス)となってwaitはinitに任せることができるようになる。

pid = Process.fork {
  puts Process.fork {
    sleep 20 # 何かしらの処理
  }

  sleep 1
}

Process.waitpid pid

まとめ

  • 親が死んだら子はinitが看取ってくれる
  • 親が死ぬまでゾンビは消えない
  • ゾンビを増やさないためには、適宜waitするかDouble Forkしてinitに面倒をみてもらう