2006-07-14

_ failmalloc

私は立場上いろんな人のプログラムを見る必要がある。 しかし、とりわけ経験不足な人が書いたコードはエラーチェックが無茶苦茶である。 要するに、失敗することを考えていない。 これには非常にうんざりさせられるが、 そもそも何が原因なのか考えてみた。

失敗するのを見ることがないのがいけない。

これが私の辿り着いた結論である。 実のところ、malloc が本当にこけるところなんて、熟練者でさえ滅多に見たことがないんじゃなかろうか。 今日のようにメモリが潤沢になると、その傾向にますます拍車がかかることになる。

そこで、いっそのこと、わざと失敗させてみることにした。 何で今までこういうものがなかったのか、多少不思議ではあるが (私が知らないだけ?)、 30分ぐらいのハックで出来上がった。 それよりウェブページを作成する方がよっぽど時間がかかってしまった。

詳細はウェブの方を見てほしいのだが、 ハックそのものより、結果の方がずっと面白い。 いろんなプログラムにLD_PRELOADで注入して遊んでみたが、 世の中で幅広く使われているプログラムでさえ、御覧の通りである。 初心者に限って...等と考えた私がバカだったらしい。

ちなみにではあるが、 私は最近GRUB以外でCやC++みたいな低レベルの言語で開発することがほとんどないため、 自分自身のプログラムにはあんまり使えないのが残念だ。 ちなみにGRUBシェルには試してみたが、 結果は完璧だった(自画自賛)。

ところで、 posix_memalignが失敗した時にNULLで埋めてくれるか なんて、 とってもタイムリーなことを井上さんが書いてくれたが、 これこそfailmallocを使えば一発で分かることなので、 さくっとやってみたのでした。 もっともposix_memalignの場合には、 alignmentに1を指定するとか、もっと手っ取り早い方法もあるにはあるのだが...

_ Ruby On Railsによって考えさせられた事

Ruby On Railsは一部で結構盛り上がっているようで、 こうしたフリーソフトウェアを用いた技術が広がりを見せることに対し、 非常に嬉しく感じている。 しかしその一方でいろいろと考えさせられる事が多いのも事実である。

私が出現当初に感じたのは、 技術的に特に秀でているとは言えない、 ということだった。 Zopeでも同様のことが簡単にできるし、 遥かに完成度も高いではないか、と。

複雑さに金が落ちる時代は本当に終わるのか? において、essa氏は

Railsの個々の機能の過不足を問題にするのはあまり意味が無い。仮に不足があったとしても、オープンソースなんだから、そういう問題点はたくさんの人が使っていくうちに自然とフィードバックによって直っていく。

と語っておられるが、 この手のフレームワークとなる技術は成熟に随分時間がかかるものであり、 その途上で頓挫してしまうことが少なくない。 Linuxは業務で使えるレベルに達するまで10年近い年月を要したし、 カーネルと比べればずっと小さいZopeも5年程かかった。

しかしながら、私は後日この第一印象を改めなければならない、と感じた。 結局のところ、技術的成熟に必要なのは、 「長期間に渡って開発に没頭してくれるユーザ」をどれだけ確保できるかにかかっている。 Ruby On Railsの上手さとは、技術ではなく、 宣伝、マーケッティングにこそあり、 それは学ぶべきものなのだ、と。

振り返ってみれば、 一時期マニアの間で話題となり、巷を席巻したZopeを、 私は業務で必要となるまで一度も使ってみたことがなかった。 それはなぜなのか。

まさにマーケッティングの一言に尽きる。 もっともZopeの場合には業務に浸透してしまったので、 あえて新し物好きの注目を惹きつける必要性がないともいえる。 しかしZopeの宣伝の不味さ加減は端から見ていて、 非常によく分かる。 実力が充分に理解されていないと感じる。

こういうマーケッティングの巧拙は、 ヨーロッパにいると、しばしば目に付くものである。 とにかくアメリカは宣伝がうまい。 ヨーロッパ、特にフランスやドイツは、 同等以上のものを作っておきながら、 宣伝活動で敗れることが多々ある。 ZopeとRuby On Railsの場合には、両方ともメイド・イン・USAなので、 これには当てはまらない。 全てのアメリカ人がうまいというわけではない。 だが、しばしばアメリカの個人や企業にはやたらと宣伝がうまくて、 宣伝能力によって市場を勝ち取ってしまう例があるのだ。 Google然り。

エンジニアはこういうのを政治活動云々等と忌避する傾向があったりするけれど、 優れた技術だけで選ばれるほど世の中甘くない。 いくら優れていても、 その事実が知らしめられなくてはユーザを得ることはできず、 つまるところ技術的にも遅れを取ってしまうことになる。 趣味の開発ならそれでもよいけれど、 ビジネスが噛んでいる場合はそうはいかない。

まあこういう技術以外の点を学んでいかなければいけないなあ、 と感じる今日この頃なのでした。 日本でZopeやっている人、もっと頑張って宣伝してあげてください。

_ メモリ確保の失敗に関する考察

今日はフランス革命の祝日で時間に余裕があるので、 久々にいっぱい書きます。

思い切りウケ狙いで作った failmalloc であったが、 狙い通りに ウケてくれて、 非常にありがたい。 まさにハック。

しかしせっかくウケてくれた人もいるので、 少し真面目な考察を加えておきたい。

そもそもなぜ失敗を確認しなければならないのか、 NULLが返って、Segmentation Faultでくたばるなら、 それでいいではないか、という向きもあるかもしれない。 しかしながら、それは「メモリ保護機能がきちんとした」システムにのみ適用できることだ。 MMUのないハードウェアやMMUを利用しないOSでは、 自動的にプロセスを止めてくれたりはしない。 ポインタ演算を含む場合には、より上位のアドレスに悪影響を及ぶこともあるだろう。 Segmentation Faultなんて出て強制終了させられるソフトウェアが全くユーザに優しくないのは言わずもがな、である。 だから、何らかの対処をしなくてはならないのだ。

この対処法がなかなか難しいのが現実である。 ちょっとしたプログラムであれば、lsみたいにエラー表示して終了すればよいだろう。 だが、そう簡単に死なれては困るソフトウェアは数多い。 例えば、システムの重要な機能を担っているプログラムの場合、 そう簡単に死なれては困る。 また、昨今のデスクトップ・アプリケーションでは、 セッションや設定の終了時保存機能が当然のものとして受け入れられている。 いきなり死んではその暇がない。 あるいは、 データベースやトランザクション、ジャーナリングに関わるプログラムでは、 中途半端な状態にすると、再起不能に陥りかねない。

私の知識の範囲内では、以下のような手段がある。

  • プロセスを監視し、死んだら再起動する。Squidなど。
  • 変なことが起きたトランザクションはとっと諦めて、初期状態に回帰する。Apacheなど。
  • 緊急時用にいくらか余分に前もって確保しておく。Linuxなど。
  • 途中で死んでも不整合が起きないアルゴリズムやデータ構造を組んでおく。多くのデータベースやジャーナリング・ファイルシステムなど。
  • 始める前に全部確保しておく。多くの組込み系アプリケーションやGRUB Legacyなど。
  • ガーベッジ・コレクションなどで空きを増やして、粘る。多くの言語処理系やGRUB 2など。
  • 他のプロセスに続きを任せる。多くのデータベースなど。
  • 諦める、無視する。多くの駄目プログラム。

どういった手段を用いるかはケース・バイ・ケースだが、 おそらく一番難しいのはフレームワークとなるソフトウェア、 特にカーネル、データベース、言語処理系などだろう。 こういった汎用目的のソフトウェアはさまざまな要求に対応しないといけないため、 どんな回復手段にも対応できる柔軟性が必要とされる。 私がインタープリタ(python、perl、ruby)を例に出しているのは、 そういった部分が実際にどうなのか知りたかったからでもある。 別に特定のプロジェクトを槍玉に上げたかった訳ではないので、 誤解なきよう。

現実にはどれも十分には信頼できないことが伺えた。 だから、こうしたソフトウェアの上位にアプリケーションを作り上げる場合、 いきなり死ぬ可能性があることを常に考慮に入れなければならない。 私はよく「本質的に複雑な問題はどうやっても複雑だ」と言っているが、 これはあくまでコーディングに関することであって、 ユーザ・インターフェースのことではない。 残念ながらスクリプティング言語をもってしても、 この問題は解決できていないようだ。 将来この「突然死」問題を解決、あるいは、少なくとも軽減するような能力を、 言語処理系に実装されていくことを希望したい。

もっとも「電源断」や「CPU炎上」にはソフトウェアだけではどうにもならないから、 いきなり死んだ場合の対処が消失することはなさそうではあるが...

本日のツッコミ(全5件) [ツッコミを入れる]
_ まつもと (2006-07-15 01:18)

お恥ずかしい。ほとんどのメモリアロケーションはチェック用のラッパ関数を経由していたのですが、1ファイルだけ直接mallocを呼び出しているものがあり、それに引っかかってました。早急に直します。

_ 田中@ボーダー (2006-07-16 19:05)

ども、お久しぶりです。(覚えてないかな?)<br><br>なんか面白い話題だったので、でてきました。<br>異常処理のロジックってのは、経験が物を言いますね。<br>分類するなら、処理を捨てて良いもの(処理自体が再度要求されるので、通信系ならば再送処理)<br>捨てられないものは、後で処理をする(一定時間待ってリトライする、他のプロセスにまかす)か、<br>メモリ確保を試みる(ガーベージコレクション等)、最後がプロセスの異常終了ですかね。<br>(組込み系ならばシステムのリセットもありますね。)

_ okuji (2006-07-17 03:48)

うわあ、田中さん、お久しぶりですねー。<br>一体何年ぶり?もう五、六年ぐらい経ちましたか。<br>今でも同じ職場に勤めていらっしゃるんでしょうか。<br><br>確かにエラー時の処理ってのは難しいものですよね。<br>「大抵上手く行って、やり直しが可能」なものは、あんまり無理して頑張らないのが一番だろうと思います。<br><br>ここではmallocを例に出してますけど、実際には他のAPI全般に当てはまる話で、どうも世の中失敗を前提に作られてないプログラムが大半なんじゃないかと最近危惧するようになってしまいました。<br>テスト駆動型の開発が流行してますが、一体こういう部分も視野に入れたテストが為されているのだろうか、と。<br>Berkeley DBなんか簡単にぶっ壊れますし。

_ 田中@ボーダー (2006-07-18 20:14)

そのくらいですかね、前に会ったのが何時だったか、、、って感じです。<br>今も札幌にいます。求人をみてフランスも悪くないなぁ。 :-)<br>とか思ったりしています。<br><br>失敗を前提したプログラムというか品質保証ってのは、分野よってかな。<br>大型系のシステム開発ならそれなりのエラー処理が設計条件として入っていますが、<br>パソコン用のアプリケーションなら考えずに作っても大きな問題になりませんしね。<br># デーモン関係だと、メモリリークがあると問題になるな、<br><br>それに、試験も難しいですからね、エラーが発生する状態とか、<br>(メモリを含む一般的なリソースの)種類等、細かくやり出すときりが<br>なくなるし、かといって、これだけやったら大丈夫だ!。とは言えないですしね。

_ まつもと (2006-07-18 23:59)

failmallocですが、malloc系が失敗したときにENOMEMを設定することを期待するプログラムが多いようです。glibcとか。

[]

トップ «前の日記(2006-06-30) 最新 次の日記(2006-08-01)»