Runtime.exec()でToo many open Files

あるシステム(JRE1.4.2_05 on Soralis8)を運用している中で、Too many open FilesのIOExceptionが発生することがありました。
pfilesコマンドでプロセスが掴んでいるファイルディスクリプタを覗いてみると、

S_IFIFO mode:0000

という、FIFOがたくさんできちゃって残りっぱなしになっています。
trussでシステムコールを監視してみると、

pipe()                                          = 7 [8]
pipe()                                          = 10 [12]
pipe()                                          = 13 [14]
fork1()                                         = 29021

とforkした後に、closeが

close(7)                                        = 0
close(12)                                       = 0
close(14)                                       = 0
close(8)                                        = 0

と4回しか呼ばれてないことが分かりました。実際にRuntime.exec()を実行しているのは、ミドルウェアの部分なので、ソースを見ることはできないのですが、おそらくProcessオブジェクトの標準入力および標準エラーをクローズしていないと推測されます。

簡単なプログラムを作り実行してみると確かに3本のストリーム全てをクローズするとFIFOが残りっぱなしになるなんてことはありません。逆に標準出力だけクローズすると同現象が起こります。

import java.io.*;

class TooManyFilesTest{
        public static void main(String[] args) throws Exception {
                for(int i=0; i<= 300; i++) {
                        Process p = Runtime.getRuntime().exec("cat");
                        InputStream in = p.getInputStream();
                        PrintStream out = new PrintStream(p.getOutputStream());
                        out.println("ABC"+ i);
                        out.close();
                }
                Thread.sleep(60000); //この隙にpfiles
        }
}


ということで教訓

Runtime.execするときは、Processオブジェクトの3つのストリーム(stdout, stdin, stderr)の全てをクローズせよ。

prototype.jsのAjaxをIE5.5に対応させる

prototype.js(確認したversionは1.4.0)はIE6.0以上をターゲットとしており、確かにIE5.5ではAjaxが動かない場合があります。ただこれは、prototype.jsをちょちょいと修正するだけで動作するようになります。

640行目で

this.transport.open(this.options.method, this.url,
  this.options.asynchronous);

XMLHttpRequestをオープンしているところがありますが、prototype.jsでは何故かmethodの指定が小文字で「get」「post」と渡さなくてはいけません。
どうもIE6.0やFirefoxはthis.transport.openの中で大文字変換がかかっているようなのですが、IE5.5はそれがされず小文字のままHTTPリクエストが送られているようです。
サーバ側のプログラムが「GET」「POST」は大文字である前提で作られていると(RFC上HTTPメソッドはcase sensitiveであるとされているので、大抵のプログラムはそう作っているはず。CGI.pmとか)、クエリー文字列をうまく解釈できずエラーとなります。


ということで、

this.transport.open(this.options.method.toUpperCase(), this.url,
  this.options.asynchronous);

と強制的に大文字に変換してやればIE5.5でも動作するようになります。

use libと@INC

通常ライブラリパスは、use libで指定するかと思いますが、環境変数や引数によって読み込むライブラリパスを切り替えたいということがあります。

#!/usr/bin/perl

BEGIN {
  if ($ENV{APL_ENV} eq 'production') {
    use lib 'production/lib';
  } elsif ($ENV{APL_ENV} eq 'test') {
    use lib 'test/lib';
  } else {
    use lib 'development/lib';
  }
  use XXX;
}

としても、環境変数APL_ENVによってライブラリパスを切り替えることはできません。
上の例の場合、常にdevelopment/libのライブラリが使われます。これはuse libがBEGINブロックとして実行されるため、if文が効かないためです。こんな時は、

#!/usr/bin/perl

BEGIN {
  if ($ENV{APL_ENV} eq 'production') {
    unshift(@INC, 'production/lib');
  } elsif ($ENV{APL_ENV} eq 'test') {
    unshift(@INC, 'test/lib');
  } else {
    unshift(@INC, 'development/lib');
  }
  use XXX;
}

と@INCを直接操作してやることで、環境切り分けができます。

Code Transcribing

Code Reading―オープンソースから学ぶソフトウェア開発技法
電子写経なるものが世の中には存在するようです。写経の効能はここによると、

 このように写経には長い歴史があり、多くの人の信仰生活に心のやすらぎを与える糧となってきました。それは身と心を調えて行う写経の心が、そのまま仏さまの教えの心に通うからにほかならないのです。そしてこの写経の心は、時代を越えて、道を求むる人にとって大きな心の支えとなりました。

 現代に生きる私たちは、写経によって静かに落ち着いた時間を大切にするとともに、祈りや願いを生活の中に活かしていく一つの証としたいものです。

だそうです。


これをソフトウェアエンジニアに置き換えると、コード写経すなわち、Code ReadingならぬCode Transcribingになります。

Code Transcribingは多くのプログラマのhack生活に心のやすらぎを与える糧となってきました。それは身と心を調えて行うCode Transcribingの心が、そのままハッカーの教えの心に通うからにほかならないのです。そしてこのCode Transcribingの心は、時代を越えて、hack道を求むる人にとっての大きな心の支えとなりました。

日々職場で汚いコードと立ち向かう私たちは、Code Transcribingによって静かに落ち着いた時間を大切にするとともに、祈りや願いをhack生活の中に活かしていく一つの証としたいものです。

プログラミング技術を学ぶには、自分でオリジナルのコードをバリバリ書いてみるのが一番だとは思いますが、なかなかいいネタが思いつかないなんてことはよくあります。そんなときは、頭を空にして先人たちのエレガントなコードを追いながらタイプしてみるのもよいのではないでしょうか。


ということで、任意のソースコードからgtypistのレッスンファイルを作成するワンライナーをどうぞ。

perl -ne 'if($.%10==1){print "I:code(".int($./10).")\nS:$_";next}print " :$_";' filename

老化防止

私は小さい頃、でたらめにキーボードを打っていたので、タッチタイピングができません。これはエンジニアにとっては、箸の使い方がオカシイ、ペンの持ち方が変、バッティングフォームがベイスターズの種田みたい、というくらい恥ずかしい問題でもあります。そこで矯正を始めることにしました。
PFU Happy Hacking Keyboard Professional 墨/無刻印 [PD-KB300BN]

  • HHK Proの無刻印を買う(キー印字がないので、手元を見ても何も分からない!)
  • gtypistを使って繰り返し練習
  • マウスは決して使わない(zsh + screen + VIM環境にする)

始めてみると、今まで薬指と小指をほとんど使っていなかったんだなぁと身にしみて感じます。すべての指を使うと脳が活性化している(気がします)。

東北大学未来科学技術共同研究センター 川島隆太教授監修 脳を鍛える大人のDSトレーニング
巷では東北大学未来科学技術共同研究センター 川島隆太教授監修 脳を鍛える大人のDSトレーニングが人気ですが、これで十分頭の体操になっています(という気がします)。

screenの思いがけない効能

.screenrcに

  hardstatus alwayslastline "[%02c]

と書いておけば、ターミナルの一番下の行にリアルタイムで現在の時刻が表示されます。別にこれはシェルのプロンプトで出力していれば、あってもなくても良いものです。しかしtelnet中に無通信状態のまま放置すると、どこかのルータが接続を切ってしまうような環境では効果があります。つまり、1分おきに実行される時刻描画のおかげで、長時間のサーバとの無通信状態を作らず接続が切れなくなるのです。

これは、screenの便利さがいまいち分からない人にもオススメです。

デキル奴ほど儲かる仕組み

「個人的にお金くれれば、いくらでも実装してやるよ」
というのはデスマ・プロジェクトでよく飛び交う発言ですが、これを本当にやってみたいと思うのです。

まず、プロジェクトマネージャは、プロジェクトのタスクを分解し、プロジェクトの予算を勘案しながら、個々のタスクに値付けします。これは、実際にタスクをこなし、成果をあげた際に各人に支払われる金額にして、プロジェクトメンバのやる気を引き起こすことを狙います。タスクには実装から顧客との折衝事までさまざまあるでしょう。ここがプロジェクトマネージャの腕の見せ所で絶妙な価格設定をするのです。

プロジェクトメンバは、それに対してタスクを引き取ります。何もしなければ、給料0円になるので積極的になります。お得なタスクであれば、多数の人が引き受けたいと申し出ることが予想されます。その場合、値付けされた価格からリバース・オークションして最安値で入札した人にタスクがアサインされます。

働けば働くほど儲かる仕組みです。これならば、給料泥棒もいなくなり、デキル奴に適正な報酬が支払われることになります。直属の上司の評価だけに依存したうさん臭い給与査定なんかも不要です。


こんな会社つくれないかなぁ...