このページは過去に掲載していたものをそのまま使用しています。

[ Home | Index ]

XIMのSEGVに対する改善法

富士インフォックス・ネット(株)システム開発部の池田さんが 送ってくださったXIMに関連したSEGVに対処するパッチです。

障害と原因のレポート

以下に池田さんが送ってくださったメールの一部をそのまま載せます。

[ 現象 ]

  dia-0.84-7 で
      ファイル → 新規ダイアグラム
      ファイル → 開く
      コマンドラインからファイル名を指定して実行
  のいずれかの操作を行うと canvas を開いた時点で SEGV を起こす


[ 環境 ]

  Kondara MNU/Linux 1.1 (i686)
  Gnome desktop

  gdk、gtk+ については次の2 つのバージョンで現象が再現した
    glib-1.2.6-0.1k1 + gtk+-1.2.6-1k6 (Kondara 1.1 デフォルト)
    glib-1.2.8-1k1 + gtk+-1.2.8-1k1 (upgrade)


[ 原因 ]

  canvas を開く際、 XIC が初期化されないまま gdk_im_begin() に渡されたため、
  SEGV が発生した。

      canvas を開く際の処理の流れ

         display.c:new_display()

	   1. ddisp 構造体を動的確保、初期化
           2. create_display_shell()

           → GDK_FOCUS_CHANGE イベント発生
 	      ddisplay_canvas_event() が call される

         disp_callbacks.c:ddisplay_canvas_event()
           3. ddisplay->ic が NULL なら create_input_dialog() を call
	      NULL でなければ gdk_im_begin() を call


  canvas を開くときなどは create_input_dialog() を call したいので

     ddisplay->ic == NULL

  でなければならないが、create_display_shell() を call する前(1.)の段階で
  ddisp->ic が初期化されていなかった。

  そのため 3. で無効な XIC が gdk_im_begin() に渡され SEGV を生じた。


[ 対処 ]

  create_display_shell() を呼ぶ前に ddisp->ic, ddisp->ic_attr を NULL で
  初期化するようにした。

  なお、focus out の際に gdk_im_end() を呼ぶようにもした。これは本現象と
  は無関係であると思われるが、GDK Reference Manual に従い念のため入れた。


[ 結果 ]

  修正後、10日間使用したが、現象は再現せず、問題なく使用できた。


[ パッチ ]

  適用方法
    dia-0.84 オリジナル版に dia-0.84-0-1.diff、dia-0.84-1-6.diff、
    dia-0.84-6-7.diff を当てた後、さらに以下のパッチを当てる

dia-0.84-7に対するパッチ

池田さんがdia-0.84-7を修正するパッチを送ってくださいました。 あらかじめ以下の差分の内容をファイル(filename)に保存しておき 、dia-0.84-7のディレクトリで patch -p1 < filenameのような感じで使ってください。

diff -uNr dia-0.84-7/app/disp_callbacks.c dia-0.84-7+2/app/disp_callbacks.c
--- dia-0.84-7/app/disp_callbacks.c	Tue Jul 11 20:44:23 2000
+++ dia-0.84-7+2/app/disp_callbacks.c	Sat Jul 22 13:10:52 2000
@@ -293,10 +293,14 @@
     
     case GDK_FOCUS_CHANGE:
 #ifdef USE_XIM
-        if(ddisp->ic == NULL)
-          create_input_dialog (ddisp);
-	else
-	  gdk_im_begin(ddisp->ic, ddisp->canvas->window);
+	if(((GdkEventFocus *)event)->in) {
+        	if(ddisp->ic == NULL)
+          	create_input_dialog (ddisp);
+		else
+	  	gdk_im_begin(ddisp->ic, ddisp->canvas->window);
+	} else {
+		gdk_im_end();
+	}
 #endif
       diagram_update_menu_sensitivity(ddisp->diagram);
       break;
diff -uNr dia-0.84-7/app/display.c dia-0.84-7+2/app/display.c
--- dia-0.84-7/app/display.c	Tue Jul 11 20:44:14 2000
+++ dia-0.84-7+2/app/display.c	Sat Jul 22 13:10:23 2000
@@ -137,6 +137,11 @@
   ddisp->visible.right = prefs.new_view.width/ddisp->zoom_factor;
   ddisp->visible.bottom = prefs.new_view.height/ddisp->zoom_factor;
 
+#ifdef USE_XIM
+  ddisp->ic = NULL;
+  ddisp->ic_attr = NULL;
+#endif
+
   create_display_shell(ddisp, prefs.new_view.width, prefs.new_view.height,
 		       filename);
 
@@ -153,10 +158,6 @@
   g_hash_table_insert (display_ht, ddisp->shell, ddisp);
   g_hash_table_insert (display_ht, ddisp->canvas, ddisp);
 
-#ifdef USE_XIM
-  ddisp->ic = NULL;
-  ddisp->ic_attr = NULL;
-#endif
 
   return ddisp;  /*  set the user data  */
 }

Yasuhiro Abe <m5031201@u-aizu.ac.jp>
Last modified: Sat Aug 26 14:25:02 JST 2000