2015年10月19日月曜日

ネイティブ クラッシュ(/system/lib64/libskia.so)

一通りダウンロード数の多いアプリの変更が済み一夜明けてみると、DeveloperConsoleにバグレポートのカウントが上がってました。


見てみるとネイティブクラッシュということでレポートを見てみると。
よくわからないクラッシュ時のログが表示されているだけ。

もうちょっとログが欲しいところではあるものの、ユーザーが送付してくれただけでも正直とてもうれしい話です。
どこで発生したのかは材料がそろっているわけではないので具体的にわからないまでも、いつものlibskia.soです。
ヒントになるとすれば、落ちた時のbacktraceで使われているポイントで判断するとかそんな感じでしょう。

backtrace:
#00 pc 0000000000134f78 /system/lib64/libskia.so
#01 pc 0000000000135340 /system/lib64/libskia.so (SkBlitMask::BlitColor(SkBitmap const&, SkMask const&, SkIRect const&, unsigned int)+152)
#02 pc 000000000013bc48 /system/lib64/libskia.so (SkARGB32_Opaque_Blitter::blitMask(SkMask const&, SkIRect const&)+36)
#03 pc 00000000001541d0 /system/lib64/libskia.so
#04 pc 00000000001581b8 /system/lib64/libskia.so (SkDraw::drawPosText(char const*, unsigned long, float const*, float, int, SkPaint const&) const+1152)
#05 pc 00000000001464ec /system/lib64/libskia.so (SkCanvas::onDrawPosText(void const*, unsigned long, SkPoint const*, SkPaint const&)+704)
#06 pc 0000000000148020 /system/lib64/libskia.so (SkCanvas::drawPosText(void const*, unsigned long, SkPoint const*, SkPaint const&)+16)
#07 pc 0000000000104adc /system/lib64/libandroid_runtime.so (android::SkiaCanvas::drawText(unsigned short const*, float const*, int, SkPaint const&, float, float, float, float, float, float)+88)
#08 pc 00000000000f083c /system/lib64/libandroid_runtime.so (android::CanvasJNI::drawText(android::Canvas*, unsigned short const*, int, int, int, float, float, int, android::Paint const&, android::TypefaceImpl*)+1208)
#09 pc 00000000000f0ae8 /system/lib64/libandroid_runtime.so
#10 pc 0000000000dd4978 /system/framework/arm64/boot.oat

見事にcanvasの操作というのがよくわかります(笑)

しかし問題はこれが何時どのように発生したのかが全く分かりません。

レポートを送信するときは、一言でもいいので発生したタイミングを書いてもらえるともう少し具体的にわかりやすくなります。

さて、今回はこれが発生したOSバージョンが5.1だったので、手持ちの5.1のTegra NOTE7で実行してみます。

デバッグは6.0のNEXUS9で動作チェックをしていたので、その時には発生しなかったのであまり気にしてなかったのですが、やはり実装が違うという事はこのような問題も色々と出てくるという事なのでしょう。

同様のエラーが出てくれれば助かるのですが、今までもエミュレータ上だと発生するとか、実機だと再現させられない場合もあったので、期待半分程度で動かしてみます。

あっさりとエラーが出ました。(笑)
エラーのタイミングは終了時に発生していました。

問題は…TegraNOTE7のデバッグができる状態になっていないので、ログを見たいために早速USBドライバーのインストールを行いたいところ。
しかしWindows 10では署名されていないドライバーやinfの書き換えを行ったドライバーのインストールができないので調べてみました。
方法は2つあるようで、一つはコマンドプロンプトからテストモードに移行させてインストールするもの。
もう一つはシフトキーを押しながらメニューの電源ボタンの再起動を実行すると起動時の設定メニューが出てくるので、そこで「署名なしのドライバーのインストールを許可する」を数字キーで選んで起動させ、デバイスマネージャから無効になっているTegraNoteのドライバーを更新し、googleのUSBドライバのinfに追記した状態でインストールしました。

怪しいUSBドライバーがいろいろなところからダウンロードできるのでそちらでもいいとも思うんですが、やっぱり気持ちが悪いですよね…。

さて実際にデバッグログを追いかけられる状態になるまでにソースも少し変更し、変更後の状態で動作確認をしてみました。

行ったことは終了時にフラグを立てているところの処理をsynchronized(this)で包んだことと、描画処理のlockCanvas~unlockCanvasとsynchronized(this)で包んだうえで、synchronized(this)の直後にフラグをチェックするようにしたことです。

最初はlockCanvas~unlockCanvasだけsynchronized(this)させれば問題が発生しなくなるかと思ったのですが、やはりきれいに処理的に記述しないと何度かやっているうちに同じようなエラーがでてクラッシュしてしまいました。
時間にしたら数十ミリ秒~数百ミリ秒程度のはずなのですが、思っている以上に再現率は高かったです。

再現してくれたおかげでこの部分の処理の流れもすっきりできました。 ただちょっと助長な点として、ループ条件の一部をループ内でチェックしている部分が気にはなりますが、半分はどうにもならないところかなとあきらめるしかなさそう。ループを中断させる形の方がすっきりしそうなので今後の課題かな?(笑)

0 件のコメント:

コメントを投稿