[Message Prev][Message Next][Thread Prev][Thread Next][Message Index][Thread Index]

Re: [MD:4310] Meadow のデッドロック?



>>>>> [meadow-develop : No.4317] にて
>>>>> "三好" = 私は書きました:
himi> > 対処療法になりますが、下記の patch のように message を使わずに 
himi> > Imm 関連の関数を直接呼び出すことで、この問題は回避できます。
himi> > commit しても構わないでしょうかね?

himi> これはだめ。Imm APIの仕様上、thread safeでないので。

三好> 了解しました。
三好> このために、メインスレッドで実行される primitive function では、
三好> Imm API をメッセージで呼び出しているのですね。

原因と対策を整理して考えてみました。

なお、この現象は、圭一さんの報告 [MD:4167] の現象と同じです。

(1) デッドロックの原因

o メインスレッド:Fset_window_configuration()@window.c にて 
  W32_BLOCK_INPUT が呼ばれて、他のスレッドをブロックする。

o メッセージスレッド:W32_BLOCK_INPUT が呼ばれると、UNBLOCK され
  るまで待機状態になる。

o メインスレッド:Fselect_window() -> Ffep_get_mode() が呼ばれる。

o メインスレッド:Ffep_get_mode() では、IME のモードを取得するた
  めに、メッセージスレッドにメッセージ送るが、メッセージスレッド
  は待機状態にあるため、応答は得られない。

→メッセージスレッドは応答待ち、メッセージスレッドは待機状態のま
  まになり、デッドロック発生。

これに限らず、クリティカルセクション(W32_BLOCK_INPUT と 
W32_UNBLOCK_INPUT の間)にて、メッセージが使われると、デッドロック
に陥る可能性があります。


(2) 対処方法

クリティカルセクション内では、メッセージスレッドが待機状態に入る
可能性があるので、メッセージを送った後で応答を待つ処理は避けるべ
きです。

対処方法としては、次のようなものが考えられます。

(a) メッセージを使う処理をクリティカルセクション外に追い出す
   (a-1) クリティカルセクションの範囲を必要最小限のものに狭める
   (a-2) メッセージを使うコードをクリティカルセクション外に移動する
(b) メッセージを使う処理をメッセージを使わないように変更する

(a-1)が一番良い方法だと思いますが、私には無理です。何が必要最小限
かを判断できないからです。

(b)は、Imm API がスレッド・セーフでないので、難しいそうです
([MD:4310])。

となると、私にできるのは (a-2)だけです。

添付の patch のような対応はどうでしょうか?

かなり、無理やりな対応な対応であることは承知しておりますが、現状
のようにデッドロックに陥るよりは、ましだと思います。



--- ./window.c.orig	2003-03-10 23:48:03.000000000 +0900
+++ ./window.c	2003-04-02 19:44:27.000000000 +0900
@@ -4893,6 +4893,18 @@
       /* The mouse highlighting code could get screwed up
 	 if it runs during this.  */
 #ifdef MEADOW
+      /* To prevent deadlock, call select-window-functions() not in
+	 Fselect_window() but here.  It may cause deadlock to call a
+	 function which handles a message in a critical section.
+      */
+      Lisp_Object select_window_functions_orig = Vselect_window_functions;
+
+      if (!NILP (Vselect_window_functions))
+	run_hook_with_args_2 (Qselect_window_functions, selected_window,
+			      data->current_window);
+
+      Vselect_window_functions = Qnil;
+      
       W32_BLOCK_INPUT;
 #endif
       BLOCK_INPUT;
@@ -5060,6 +5072,9 @@
 	 near the beginning of this function.  */
       selected_window = Qnil;
       Fselect_window (data->current_window);
+      /* restore it now. */
+      Vselect_window_functions = select_window_functions_orig;
+
       XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
 	= selected_window;


--
三好 雅則 mailto:miyoshi@xxxxxxxxxxxxxxxx
          http://www.boreas.dti.ne.jp/~miyoshi/ (Meadow2 のページ始めました)