Fix deadlock issue when a keyboard is unbound 90/304190/2
authorInhong Han <inhong1.han@samsung.com>
Thu, 11 Jan 2024 06:51:57 +0000 (15:51 +0900)
committerDoyoun Kang <doyoun.kang@samsung.com>
Fri, 12 Jan 2024 00:15:19 +0000 (00:15 +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 7e9004f368e4526b3894afe061a2b542d72776bf..ced227c19ed2ebda73313d90ae0a27febd357a88 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 */