Home > Archives > 2009-12

2009-12

eclipseでphpコードをデバッグするとApacheが落ちる

どうも、うしねずみです。
最近eclipseを使ったPHPの開発でハマった(ハマっている)ので書きます。

いまPHPの開発にeclipseのパッケージの一つである、Eclipse for PHP Developersを使っているのですが、どうもコレ、Vistaとの相性が悪いらしい。というより、PHPのデバッガとVistaの相性が悪いらしい。

この開発環境は
Window>Preference>PHP>Debug
のPHP Debuggerの項目でXDebugとZend Debuggerを選べるのですが、ネットで調べてみるとVistaPCでXDebugを使ってデバッグするとApacheが落ちるらしい。私はZendを使っていたので関係ないかと思いきや、Apacheが落ちる落ちる。

最初は2,3回に1回だったので落ちたら再起動して我慢していたのですが、そのうち落ちる頻度が増え、PHPのソース内で読み込んでいるswfファイル(Flexアプリケーション)の挙動まで安定しなくなってきました。もう少し具体的に言うと、Flexアプリ側からPHPにアクセスしてDBからデータを拾ってほしいのですが、PHPから正常に値が返ってこない。最初はFlexアプリ側でどんなに探してもバグらしきものが見つからなくて困りました。しかしブラウザからアクセスすると正常な挙動を示すので、どうやらPHPのデバッガのせい。しまいには、eclipseまで落ちまくるようになって、ホントに困りました。

今のところブラウザからアクセスした感じではアプリ全体にバグがなさそうなのでいいですけど、このままだとPHP部分とFlex部分の結合テストができないなー。。。
あー、面倒だ。

SVNでマージしようとしたらRetrieval of mergeinfo unsupported

どうも、うしねずみです。

最近Flexアプリをeclipse + FlexBuilderプラグイン + subclipseで開発しています。subclipseって言うのはeclipse上で使えるSVNクライアントのプラグインです(他にはsubversiveというのが有名らしい)。

それで、今日コードをSVNリポジトリのtrunkにマージしようとしたら問題が。。。

Retrieval of mergeinfo unsupported by “svn+ssh://hogehoge”

って言われるのです。
どうやら、SVNサーバのバージョンが古くて、SVNクライアント側が必要としている情報が見つからないらしい。ちなみに subclipseのバージョンは1.6.5で、SVNサーバのバージョンは1.2.3。SVNのバージョンは”svn –version”で確認できます。

さて問題が起きた流れを説明してみます。

まず、マージしたいプロジェクトを右クリックして「Team」>「マージ」を選択します。するとマージのダイアログが立ち上がります。
ここです!
私は機能ブランチが完成してトランクにマージしようとしていたので「Reintegrate a branch」 を選びました。これが失敗の原因。 私が使ってるバージョンのsubclipseでは、ブランチを再統合しようとすると、マージすべきリビジョンの範囲をブランチの過去のマージの情報から勝手に取得してくれるっぽいのですが、SVNサーバのバージョンが古いと「ブランチの過去のマージの情報」っていうのが残らないらしく、「そんな情報はないよ」みたいに怒れられるっぽいです。

なので「Merge a range of revisions」を選んで、手動でマージするリビジョン範囲を指定しましょう。
なお、この場合の注意点は、今回どのリビジョンまでをマージしたかを記録しておかないと、次のマージの時にマージすべきリビジョン範囲が分からなくなります。
例えば今回リビジョン1000までマージしたのなら、次回のマージは1001~HEADリビジョンとなるはずです。

SVNはマージの方法とか理解しにくくていつも苦労します。それから「リビジョン」に対する考え方がSVNのコマンドラインクライアントとtortoiseSVN(メジャーなSVNクライアントソフト)では違うらしく、注意が必要です。

TortoiseSVN とコマンドラインクライアントを比較すると、リビジョン範囲を指定する方法に重要な違いがあります。これを思い浮かべる簡単な方法は、フェンスの柱と、フェンスの板について考えることです。コマンドラインクライアントでは、 で指定した 2 本の 「フェンスの柱」 のリビジョンを使用して、マージする変更を指定します。TortoiseSVN では、「フェンスの板」 を使用して、マージする変更セットを指定します。マージするためのリビジョンを指定するログダイアログを使用する場合、チェンジセットとしてどこに各リビジョンが現れるか、明白になるためです。かたまりとしてリビジョンをマージしていると、subversion book にある方法では、今回 100-200 をマージし、次回に 200-300 をマージすることになります。TortoiseSVN では、今回 100-200 をマージし、次回に 201-300 をマージします。この違いは、メーリングリストでたくさんの論争を巻き起こしてきました。私たちは、コマンドラインクライアントと違うことを認めます。しかし、大多数の GUI ユーザにとって、私たちが実装した方法の方が理解しやすいと信じています。

でも、SVNが無い開発はデグレしまくるだろうし、恐ろしくてやってられません。以前マージを手動で(WinMergeというマージツールを使って)一つずつファイルを開いてやったことがありましたが、死にました。
これからもお世話になります、SVN。

Flexで画像のロードが終わるまで待機したい(Sleepが無い!!)

どうも、うしねずみです。
Flexでの画像のロードについて、悩んだので書いてみます。どうやらFlexにはSleep関数が無いようで、そのせいで色々悩みました。まずは、画像をロードする方法をまとめてみます。

方法その1: LoaderをそのままaddChildする

例えばロードした表示するだけの時は以下のように書きます。

loaderをuicにaddChildしたものをaddChildすれば画像が表示されるというちょっと不可思議な感じ。

方法その2: COMPLETEイベントのリスナーを登録しておく

方法その1だと、画像を表示するだけなら出来ましたが、画像を扱ってどうにかしたいときは困ります。そういう時は以下の方法。

4行目でloadComplete関数をロード完了時のイベントリスナに登録しています。よって、画像の読み込みが終わるとloadComplete関数に制御が飛んで、その中で画像を使った処理ができます。test関数はロードが完了する前にリターンされます。よってtest関数を呼んだ側の処理が画像のロードの間待たされるわけではありません。

さて、ここで問題が

実はこの「ロードが終わる前に制御が戻る」という性質が厄介だったりするのです。最近画像のラッパーを作っていたのですが、その時に「画像のロードが終了するまで呼び出し側の実行を待機したい」ということがありました。例えば以下のようなラッパーを作ったとします。

このクラスは、画像のアドレスを渡してnewすると、コンストラクタ内で画像をロードしておいてくれるクラスです。これだけだとアドレスと画像を持っているだけですが、他にもこの画像に関する様々な情報をまとめて持たせるためのクラスです。
さて、このクラスは例えば以下のように使われます。

ここで問題が生じるのです。MyImageWrapperのコンストラクタはロード処理を開始するだけで、ロードが終わるまで待ちません。なのでまだMyImageWrapperのloadCompleteが呼ばれないうちに制御が返ってきます。すると2行目でまだmyImage.imageDataはnullなので、「nullはaddChildできません」というエラーになるのです。
じゃー答えは簡単。imageDataがnullじゃなくなるまで待てばいいんだな、と思って次のように書き変えました。

ところが、このソースを実行してみると、永久にloadCompleteが呼ばれず、5行目にたどりつくことができません。Flex(Flash)の中で「CPUが空き状態になるまでloadCompleteの実行は待機する」という仕様になっているのでしょうか。

じゃあ空ループじゃなくてSleepすればいいんだな。と思って調べたのですが、どうやらFlexにはSleepが無い模様。
さて、困った。

Timerを使って実装することもできなくはないです。以下のようになります。

タイマは、一定時間ごとに登録したリスナを呼んでくれます。ここでは無名関数をその場で定義して登録しています。つまりこのタイマは100msごとに画像のロードが終わってるかどうかをチェックして、もし終わってたらaddChildを済ませて、自分自身(タイマ)を止めてくれます。
しかしこれはこれでなんか面倒だしすっきりしません。また、timer.start()のところで実行が待機するわけではないので別のところで画像データを使いたくなったときに既に画像のロードが終わっている保証がありません。

例えばユーザには「画像ロードボタン」と「画像編集ボタン」が提示されているとします。「画像ロードボタン」はユーザが指定したURLから画像をロードしてくるボタンです。「画像編集ボタン」はロードした画像に何か編集を加えるボタンです(モノクロに変換するなど、何でもよい)。仮にタイマを使っても、「画像ロードボタン」を押したあとロードが完了する前に制御がユーザに戻ってしまいます。その後すぐに「画像編集ボタン」を押されると、「画像編集ボタン」のイベントハンドラは既に画像が読み込まれていることを期待して読みに来ますが、実際は画像データはありません。

結局、対策としては、画像がロード済みかどうか(null)じゃないかどうか、使う前に毎回チェックして、ロードが済んでいなかったら何もしないっていうこと。それしかないのかなー。
なんとかSleep的な処理ができないかなーと思って疑似Threadライブラリ(そうめん?)なんかも試してみた。Threadが終了するまで待つことができるjoin関数が使えるかと思ったけど、Threadの終了を待てるのはThreadだけのようで、Threadではない実行部分で何かの処理を待機することはできない模様。
完全に手詰まりです。

ところで、Sleepが無い理由を自分なりに考えてみた。
Flexは基本的にイベント駆動型のアプリを作るためにあるはずなので、一つのイベントが全体をSleepさせるような処理を書くべきではない、ということなのだと思う。
でも、なんか、かゆい所に手が届かないむずむずというか、、、初めてSchemeを触った時に「破壊的代入を行わないプログラミング」が難しいパズルのようでどうしても頭に入ってこなかった時のような気持ち悪さ。
まー、修行が足りないってことですかね。

OpenCVのcvLoadImageの戻り値がNULLになる

どうも、うしねずみです。
今日は小ネタです。

最近、ちゃんとファイルがあるのにOpenCVのcvLoadImageがNULLしか返さないという現象に遭遇しました。どうやら画像のロードが失敗している様子。パスが間違っているかなーと思ってロードするファイルパスを確かめるけど、何度見ても合ってる。しまいにはエクスプローラのアドレス欄から絶対ファイルパスをコピペしてみたけど、それでもNULLしか返ってこない。

原因はVisual StudioとVistaでした。
以前どこかで「Visual StudioをVistaで使う時、管理者権限で実行しないと不具合が起きることがある」という記事を見たことがあったのですが、まさにそれ。Visual Studioをいったん閉じて、管理者権限で実行すると、なんの問題もなくプログラムが実行できました。

ほんと、こういう分かりにくいの、やめてほしいです。。。
※実行ファイルを右クリックして、「プロパティ」を開き、「互換性」タブの「管理者としてこのプログラムを実行する」にチェックを入れておくと、ダブルクリックで起動するときも含めて常に管理者権限で実行されます。

Home > Archives > 2009-12

Search
Feeds

Return to page top