synaptic のバグ追い最終回 [Vine Linux]
errata を発行したらすぐに書こうと思ってたけど、lenovo のミニキーボードで遊んでて書きそびれていた、synaptic からパッケージの再インストールができないバグを追っかけた話の最終回です。
今までに三回ほどブログに書いてますが、
バグ追い初挑戦中
バグ追い継続中
バグ追い継続中2
結局途中で行き詰ってしまったので、しばらく気分転換して、また振り出しから初めてみることに。
まず、設定類を元に戻して再インストールを試してみると、やっぱり、
と表示されてしうので、まずはこのメッセージの package ... is already installed を取っ掛かりにしてみます。
このメッセージを grep してソースを検索してみると、rpm-4.8.1/lib/rpmps.c に定義されていることから、rpm 自体は「既にインストールされているパッケージをもう一度インストールしようとしている」と認識してエラーを出していることが想定できます。
で、デバッガ (nemiver) で追いかけてみると、確かに rpmtsRun → checkProblems に行ってインストール前のチェックでエラーになっていることが確認できました。
さて、それじゃあと言う事で、再度 apt の設定ファイルに
を追記した上でデバッガで追いながらステップ実行してみると、、、確かにエラーメッセージは出ているものの、さっきエラーを出してたところは問題なく実行されているように見える。
なんでだ?と思いながらしばらく考えていたら、ふと「もしかしてエラーメッセージはでてるけど、再インストール自体は成功してるんじゃ?」と思いついたので、試しに適当なファイルを削除してからそのファイルを提供しているパッケージを再インストールしてみると、ちゃんとファイルが作られていた!
なんだよーーー、とちょっとがっくりきたものの、これで一歩前進できたので、次はどこで
なるメッセージが出力されているのかを調べていきます。
最初はデバッガで追ってみたものの、そのままではどこが問題なのか分からなかったので、実際にインストールのプログレスを表示している synaptic-0.57.2/gtk/rginstallprogress.cc の RGInstallProgress::updateInterface() 内に printf 文を仕込んで、通常のインストール時と再インストール時とでどう処理が違うのかを確認してみました。
すると、IF ブロックの通り方が違うことに気づいたので、ポイントとなるコードの、
の意味を理解する為に、ウェブで検索して c++ での map や iterator の使い方を調べた結果、出力メッセージ中に特定の文字列が無いのかを判別する所で失敗してるのが分かりました。
(↑そもそもプログラミングができない人間がデバッグしている点にムリがあります)
ということは、新規インストールの時は _summaryMap にちゃんと文字列が設定されているのに、再インストールの時にはそれが設定されていないから結果として(処理は成功しているのに)変なエラーメッセージが出てしまう、ということになるので、この _summaryMap をに値を入れているとこを探していくと、gtk/rginstallprogress.cc で
と、FInstall の時だけ _summaryMap に値を入れているのが分かるので、ここを
と、再インストールの時にも設定されるようにしてやることで、変なエラーメッセージが出ないようになり、正しく再インストールができるようになりました。
ということで、4年越しのバグをなんとかして解消できたので、自分としてはとても満足してます。
あと「諦めなければなんとかなるもんだ!」という良い経験になりました。
やったぜ!!
今までに三回ほどブログに書いてますが、
バグ追い初挑戦中
バグ追い継続中
バグ追い継続中2
結局途中で行き詰ってしまったので、しばらく気分転換して、また振り出しから初めてみることに。
まず、設定類を元に戻して再インストールを試してみると、やっぱり、
While preparing for installation: package vine-release-5.2-1vl5.noarch is already installed E: Error while running transaction
と表示されてしうので、まずはこのメッセージの package ... is already installed を取っ掛かりにしてみます。
このメッセージを grep してソースを検索してみると、rpm-4.8.1/lib/rpmps.c に定義されていることから、rpm 自体は「既にインストールされているパッケージをもう一度インストールしようとしている」と認識してエラーを出していることが想定できます。
で、デバッガ (nemiver) で追いかけてみると、確かに rpmtsRun → checkProblems に行ってインストール前のチェックでエラーになっていることが確認できました。
さて、それじゃあと言う事で、再度 apt の設定ファイルに
APT::Get::ReInstall "true";
を追記した上でデバッガで追いながらステップ実行してみると、、、確かにエラーメッセージは出ているものの、さっきエラーを出してたところは問題なく実行されているように見える。
なんでだ?と思いながらしばらく考えていたら、ふと「もしかしてエラーメッセージはでてるけど、再インストール自体は成功してるんじゃ?」と思いついたので、試しに適当なファイルを削除してからそのファイルを提供しているパッケージを再インストールしてみると、ちゃんとファイルが作られていた!
なんだよーーー、とちょっとがっくりきたものの、これで一歩前進できたので、次はどこで
While preparing for installation: vine-release-5.2-1vl5.noarch
なるメッセージが出力されているのかを調べていきます。
最初はデバッガで追ってみたものの、そのままではどこが問題なのか分からなかったので、実際にインストールのプログレスを表示している synaptic-0.57.2/gtk/rginstallprogress.cc の RGInstallProgress::updateInterface() 内に printf 文を仕込んで、通常のインストール時と再インストール時とでどう処理が違うのかを確認してみました。
すると、IF ブロックの通り方が違うことに気づいたので、ポイントとなるコードの、
map<string, string>::const_iterator I = _summaryMap.find(line);
の意味を理解する為に、ウェブで検索して c++ での map や iterator の使い方を調べた結果、出力メッセージ中に特定の文字列が無いのかを判別する所で失敗してるのが分かりました。
(↑そもそもプログラミングができない人間がデバッグしている点にムリがあります)
ということは、新規インストールの時は _summaryMap にちゃんと文字列が設定されているのに、再インストールの時にはそれが設定されていないから結果として(処理は成功しているのに)変なエラーメッセージが出てしまう、ということになるので、この _summaryMap をに値を入れているとこを探していくと、gtk/rginstallprogress.cc で
void RGInstallProgress::prepare(RPackageLister *lister) { for (unsigned int row = 0; row < lister->packagesSize(); row++) { RPackage *elem = lister->getPackage(row); // Is it going to be seen? if (!(elem->getFlags() & RPackage::FInstall)) continue; const char *name = elem->name(); const char *ver = elem->availableVersion(); const char *pos = strchr(ver, ':'); if (pos) ver = pos + 1; string namever = string(name) + "-" + string(ver); _summaryMap[namever] = elem->summary(); }
と、FInstall の時だけ _summaryMap に値を入れているのが分かるので、ここを
// Is it going to be seen? - if (!(elem->getFlags() & RPackage::FInstall)) + if (!((elem->getFlags() & RPackage::FInstall) || (elem->getFlags() & RPackage::FReInstall)))
と、再インストールの時にも設定されるようにしてやることで、変なエラーメッセージが出ないようになり、正しく再インストールができるようになりました。
ということで、4年越しのバグをなんとかして解消できたので、自分としてはとても満足してます。
あと「諦めなければなんとかなるもんだ!」という良い経験になりました。
やったぜ!!
コメント 0