致命的 #968
完了抽出タブのアイコンが参照できないと落ちる
0%
説明
抽出タブに設定していたアイコンを移動させた後に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: )>
が渡されており、
アイコンを開こうとするも存在しないので失敗といった流れです。
ファイル
バックトレース
/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)>'
toshi_a 初音 さんが7年以上前に更新
- トラッカー を バグ から 致命的 に変更
- 担当者 を toshi_a 初音 から あひる 家鴨 に変更
- バックトレース を更新 (差分)
エラー画像が表示されるべきであるという意見には賛成です。
このバグについての考察¶
最終的に画像を表示する為に使っている Gtk::WebIcon
というUIウィジェットは、画像のURLを文字列で受け取ってそれを描画する Gtk::Image
を生成することでした。この時、URLの参照に失敗するとエラー画像が表示されます。
3.5で新たにURLのほかにPhotoModelも受け付けるようになりましたが、画像の実態が存在しない場合には log.txt のような例外が発生します。URLのときと挙動が違うのは考慮漏れであって意図したものではありません。
根本的には、エラー画像を返すところでGtkの例外を投げてしまっているというバグによるものです。
修正案¶
ちょっと考えましたが、この修正方針ではなく、 次のどちらかのような振る舞いにしたほうが良いと思います。
Diva::Model::PhotoMixin#pixbuf
の振る舞いを、画像がない場合は同じサイズのエラー画像のPixbufを返すようにする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については考慮しなくて良いかなと思います。
あひる 家鴨 さんが7年以上前に更新
1. で進めてみようと思い、ひとまず例外を発生させてそれをキャッチして notfound を表示するところまではできました。
ここまでをブランチ: topic/968-rescue-skin-not-found にプッシュしました。
ご指摘の通り notfound が取得できなかった場合の処理に関しては、別途必要かもしれません。
試しに notfound.png を削除してみたところ見事に落ちました。
ただ、notfound.png が取得できなかった場合というものを考えた場合、それは Skin 側の問題な気がします。
修正が必要だとしたら Skin 側で落ちないような例外処理を何かしら用意する方がいい気がしますが、いかがでしょうか。
toshi_a 初音 さんが7年以上前に更新
無限再帰に陥ってしまうのかなと思ってましたが、確かにコードを見たところ、PixbufErrorを投げそうですね。
このチケットでは、notfound画像が無い時には例外を投げる(クラッシュする)ので十分だと思います。