Fix deadlock issue when a keyboard is unbound 91/304191/1
authorInhong Han <inhong1.han@samsung.com>
Thu, 11 Jan 2024 06:51:57 +0000 (15:51 +0900)
committerInHong Han <inhong1.han@samsung.com>
Fri, 12 Jan 2024 00:16:44 +0000 (00:16 +0000)
When the main thread flushes events, it destroys a client and unbinds a
keyboard. When the keyboard is unbound, the main thread locks a keyboard
resource/focused mutex, which can cause a deadlock if the input thread
also locks the same mutex and requests main thread boosting.
Therefore, the main thread should not be boosted while the input thread
has locked the keyboard resource/focused mutex.

Change-Id: I3466b9c05617f21a5223afba01be35fe769273d5

src/bin/e_keyrouter_wl.c

index 7e9004f..ced227c 100644 (file)
@@ -62,6 +62,11 @@ _e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, enum wl_keyboard_ke
         ELOGF("INPUT", "wl_keyboard_send_key:%s:%s|B|", NULL, (state ? "PRESS" : "RELEASE"), ev->keyname);
      }
 
+   if (focused)
+     g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
+   else
+     g_mutex_lock(&e_comp_wl->kbd.resource_mutex);
+
    EINA_LIST_FOREACH(key_list, l, res)
      {
         wc = wl_resource_get_client(res);
@@ -85,6 +90,11 @@ _e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, enum wl_keyboard_ke
         TRACE_INPUT_END();
      }
 
+   if (focused)
+     g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
+   else
+     g_mutex_unlock(&e_comp_wl->kbd.resource_mutex);
+
    if (e_config->key_input_ttrace_enable)
      {
         TRACE_INPUT_END();
@@ -126,9 +136,7 @@ e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, Eina_Bool pressed, s
 
    if (!focused)
      {
-        g_mutex_lock(&e_comp_wl->kbd.resource_mutex);
         _e_keyrouter_wl_key_send(ev, dev, state, e_comp_wl->kbd.resources, EINA_FALSE, client, surface);
-        g_mutex_unlock(&e_comp_wl->kbd.resource_mutex);
         return EINA_FALSE;
      }
 
@@ -141,13 +149,11 @@ e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, Eina_Bool pressed, s
              struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
              if (surface)
                {
-                  g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
                   if (e_comp_wl->kbd.focused)
                     {
                        wc = wl_resource_get_client(surface);
                        _e_keyrouter_wl_key_send(ev, dev, state, e_comp_wl->kbd.focused, EINA_TRUE, wc, surface);
                     }
-                  g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
                }
 
              /* update modifier state */