プロジェクト

全般

プロフィール

致命的 #968

抽出タブのアイコンが参照できないと落ちる

あひる 家鴨5ヶ月前に追加. 3ヶ月前に更新.

ステータス:
終了
優先度:
通常
担当者:
対象バージョン:
開始日:
2017-01-12
期日:
進捗率:

0%

プラグイン名:
core/plugin/gui/tablike.rb
バックトレース:

/Users/ahiru/mikutter/source/core/mui/gtk_photo_pixbuf.rb:63:in `initialize': ファイル '/Users/ahiru/mikutter/others/Slack_Mark_Web.png' のオープンに失敗しました: No such file or directory
from /Users/ahiru/mikutter/source/core/mui/gtk_photo_pixbuf.rb:63:in `new'
from /Users/ahiru/mikutter/source/core/mui/gtk_photo_pixbuf.rb:63:in `pixbuf'
from /Users/ahiru/mikutter/source/core/mui/gtk_photo_pixbuf.rb:34:in `load_pixbuf'
from /Users/ahiru/mikutter/source/core/mui/gtk_webicon.rb:40:in `load_model'
from /Users/ahiru/mikutter/source/core/mui/gtk_webicon.rb:28:in `initialize'
from /Users/ahiru/mikutter/source/core/plugin/gtk/gtk.rb:513:in `new'
from /Users/ahiru/mikutter/source/core/plugin/gtk/gtk.rb:513:in `tab_update_icon'
from /Users/ahiru/mikutter/source/core/plugin/gtk/gtk.rb:284:in `block (2 levels) in <top (required)>'

再現手順:

説明

抽出タブに設定していたアイコンを移動させた後にmikutterを起動しようとしたところ、落ちました。
起動時に呼ばれるtab_update_icon::Gtk::WebIcon.newで落ちます。
該当箇所は source:core/plugin/gtk/gtk.rb#L511 です。

UserConfigからアイコンのパスが取得され、#<Plugin::Photo::Photo: file:/path/to/tab/icon/icon.png (state: )> が渡されており、
アイコンを開こうとするも存在しないので失敗といった流れです。

log.txt 表示 - 落ちたときのログ (921 Bytes) あひる 家鴨, 2017-01-12 15:51

関係しているリビジョン

リビジョン 429ddf8b (差分)
あひる 家鴨3ヶ月前に追加

抽出タブのアイコンが参照できないと落ちる問題を修正 refs #968

アイコンをセットする際に `File.exist?` でそのファイルの存在を確認し、ない場合は `Skin['notfound.png']` を設定するようにした

リビジョン 3a34f0dc (差分)
あひる 家鴨3ヶ月前に追加

抽出タブのアイコンが参照できないと落ちる問題を修正 refs #968

一度 pixbuf を取りに行き、例外発生時にキャッチし Skin['notfound.png'] を返すように修正

履歴

#1 あひる 家鴨3ヶ月前に更新

  • ステータス新規 から パッチ適用待 に変更
  • 担当者toshi_a 初音 にセット
  • プラグイン名core/plugin/gui/tablike.rb にセット

ブランチ: topic/968-tab-icon-missing にコミットしました。

#2 あひる 家鴨3ヶ月前に更新

今回はタブの読み込み時に発生するということで、tablikeでPhotoModel生成前にFileTestするようにしましたが、PhotoModel自身がFileTestするような仕組みを持つべきか悩みました。
その辺どうなんでしょうか。
PhotoModelがFileTestの機能を持つべきか、あるいは持たずに生成前にチェックするか。

#3 toshi_a 初音3ヶ月前に更新

  • トラッカーバグ から 致命的 に変更
  • 担当者toshi_a 初音 から あひる 家鴨 に変更
  • バックトレース を更新 (diff)

エラー画像が表示されるべきであるという意見には賛成です。

このバグについての考察

最終的に画像を表示する為に使っている Gtk::WebIcon というUIウィジェットは、画像のURLを文字列で受け取ってそれを描画する Gtk::Image を生成することでした。この時、URLの参照に失敗するとエラー画像が表示されます。
3.5で新たにURLのほかにPhotoModelも受け付けるようになりましたが、画像の実態が存在しない場合には log.txt のような例外が発生します。URLのときと挙動が違うのは考慮漏れであって意図したものではありません。
根本的には、エラー画像を返すところでGtkの例外を投げてしまっているというバグによるものです。

修正案

ちょっと考えましたが、この修正方針ではなく、 次のどちらかのような振る舞いにしたほうが良いと思います。

  1. Diva::Model::PhotoMixin#pixbuf の振る舞いを、画像がない場合は同じサイズのエラー画像のPixbufを返すようにする
  2. Plugin::Photo::Photo#[] が呼ばれた時に画像の有無を判断して、無い場合は Skin['notfound.png'] の結果を返す

利点

1の方針は比較的簡単ですが、画像が破損しているといった理由でも GdkPixbuf::Pixbuf.new は例外を投げるので、ファイルの存在確認よりは、とりあえず呼び出して例外をキャッチし、エラー画像のPixbufを返すという実装が良さそうです。PhotoMixinは全てのPhoto系のModelで利用されるので、ここで対応すれば他のPhotoModelにも同様の機能が備わり、例えば存在しないスキン画像を読み込もうとした時にエラー画像が表示されるようになります。

2については、予め存在を確認するため、1つの画像についてmikutterが存在を確認する回数が減りそうです。また、Pixbuf以外のオブジェクトで画像を取得する手段が追加された時に、エラー画像の処理を再実装する必要がなくなりそうです。

欠点

1は、Skinにも適用されるため Skin['notfound.png'] が読み込めなかった場合にも Skin['notfound.png'] の内容を読み出そうとして無限再帰に陥りそうなので、notfound.pngを特別扱いする必要があります。
notfound.pngが読み込めなかった場合にどうするかも決める必要があります。

2は、他のPhoto系のModel全てで同様の実装をする必要が出てきてしまうという問題があります。また、PhotoModelを作った時には存在したが、参照した時には消えていた場合などに対応できません。

個人的には、1の案をベースに考えて、2については考慮しなくて良いかなと思います。

#4 あひる 家鴨3ヶ月前に更新

1. で進めてみようと思い、ひとまず例外を発生させてそれをキャッチして notfound を表示するところまではできました。
ここまでをブランチ: topic/968-rescue-skin-not-found にプッシュしました。

ご指摘の通り notfound が取得できなかった場合の処理に関しては、別途必要かもしれません。
試しに notfound.png を削除してみたところ見事に落ちました。

ただ、notfound.png が取得できなかった場合というものを考えた場合、それは Skin 側の問題な気がします。
修正が必要だとしたら Skin 側で落ちないような例外処理を何かしら用意する方がいい気がしますが、いかがでしょうか。

#5 toshi_a 初音3ヶ月前に更新

無限再帰に陥ってしまうのかなと思ってましたが、確かにコードを見たところ、PixbufErrorを投げそうですね。
このチケットでは、notfound画像が無い時には例外を投げる(クラッシュする)ので十分だと思います。

#6 あひる 家鴨3ヶ月前に更新

  • 担当者あひる 家鴨 から toshi_a 初音 に変更

了解です。
topic/968-rescue-skin-not-found に修正をあげているので確認とマージをお願いします。

#7 toshi_a 初音3ヶ月前に更新

  • ステータスパッチ適用待 から 終了 に変更

確認できました。hotfix/3.5にmergeしました。

他の形式にエクスポート: Atom PDF