2014年2月9日 星期日

從 third-party library 的 console 錯誤訊息找出更多線索

最近遇到一個不錯的小例子, 可以比較完整地記錄用到的相關指令。更多關於 gdb 的說明, 見 gdb 初步心得

問題

Ubuntu 下執行程式後看到 "Gtk-WARNING **: cannot open display:", 然後程式就掛了。

解決過程

為了獲取更多線索, 我想找出是那段程式輸出這個錯誤訊息。由 "Gtk-WARNING" 可知是 Gtk+ 函式庫輸出的錯誤訊息。所以得先取得 Gtk+ 的 debug symbol 和原始碼:

$ dpkg -l | grep gtk
...
ii  libgtk2.0-0
...

找出已安裝的 Gtk+ 函式庫叫做 libgtk2.0, 接著找出它對應的 debug symbol package 和原始碼:

$ aptitude search libgtk2.0
i   libgtk2.0-0             - GTK+ graphical user interface library
...
i   libgtk2.0-0-dbg         - GTK+ libraries and debugging symbols
...
i   libgtk2.0-dev           - development files for the GTK+ library
...

然後安裝 debug symbol, 還有取得 Gtk+ 的原始碼:

$ aptitude install libgtk2.0-0-dbg
$ apt-get source libgtk2.0-dev

從取得的原始碼找看看有沒有 "cannot open display":

$ cd gtk+2.0-2.24.10/
$ grep "cannot open display" -R .
./gtk/gtkmain.c:      g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
./gdk/gdk.c:      g_warning ("cannot open display: %s", display_name ? display_name : "");
./.pc/071_no_offscreen_widgets_grabbing.patch/gtk/gtkmain.c:      g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
./.pc/100_overlay_scrollbar_loading.patch/gtk/gtkmain.c:      g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
./ChangeLog.pre-2-12:   * gtk/gtkmain.c: (gtk_init): Fix "cannot open display" error message

讀一下字串出現相關的位置, 找出函式 gtk_init_check 和 gdk_init_check。看來沒有找錯方向, 於是可以用 cgdb 執行程式, 進入 gdb 後輸入:

(gdb) b gtk_init_check
(gdb) b gdk_init_check
(gdb) directory /my/path/to/gtk+2.0-2.24.10/
(gdb) set substitute-path /.../gtk+2.0-2.24.10/ /my/path/to/gtk+2.0-2.24.10/
(gdb) r
  • directory 用來載入 Gtk+ 原始碼。debug symbol package 裡沒有含這部份。
  • 編譯封裝 Gtk+ 的路徑十之八九和我放 Gtk+ 原始碼的路徑不同, 所以要用 set substitute-path 替換路徑, gdb 才知道如何顯示對應的原始碼。上面的 "..." 是執行 backtrace 時看到的路徑, 這裡簡化用 "..." 表示。

再來就在中斷點附近輸出收到的值, 看看 backtrace, 看看附近的原始碼, 獲得更多線索後就解決問題了。原來是我忘了呼叫 setenv("DISPLAY", ":0"), gdk_init_check() 發現無法產生 GdkDisplay, 所以就掛了。

沒有留言:

張貼留言

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...