summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorfujiwarat <takao.fujiwara1@gmail.com>2012-04-06 12:11:35 +0900
committerfujiwarat <takao.fujiwara1@gmail.com>2012-04-06 12:11:35 +0900
commit991eebc31aa605fbce03edda6eaecfd06c2fcb1b (patch)
treeb6019dabae01e9a85712cf6ff9e93656f9ec7187 /client
parentb620e0bcda97934d6927b7cdde300598ac5de45f (diff)
downloadibus-991eebc31aa605fbce03edda6eaecfd06c2fcb1b.tar.gz
Fix ibus-x11 SEGV in _process_key_event_done.
IMForwardEvent() calls _Xi18nFindClient() and it could return NULL. Maybe the connect_id would be disconnected during the async process_key_event. This fix checks XIM_DISCONNECT in ims_protocol_handler() to cancel IMForwardEvent() in _process_key_event_done(). BUG=RH#769135 TEST=Linux desktop Review URL: https://codereview.appspot.com/5498090
Diffstat (limited to 'client')
-rw-r--r--client/x11/main.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/client/x11/main.c b/client/x11/main.c
index 65451aba..8550a538 100644
--- a/client/x11/main.c
+++ b/client/x11/main.c
@@ -464,6 +464,13 @@ _process_key_event_done (GObject *object,
g_error_free (error);
}
+ if (g_hash_table_lookup (_connections,
+ GINT_TO_POINTER ((gint) pfe->connect_id))
+ == NULL) {
+ g_slice_free (IMForwardEventStruct, pfe);
+ return;
+ }
+
if (retval == FALSE) {
IMForwardEvent (_xims, (XPointer) pfe);
}
@@ -600,29 +607,52 @@ _free_ic (gpointer data, gpointer user_data)
}
static int
-xim_close (XIMS ims, IMCloseStruct *call_data)
+_free_x11_iconn_from_id (CARD16 connect_id)
{
X11ICONN *conn;
- LOG (1, "XIM_CLOSE connect_id=%d",
- call_data->connect_id);
-
conn = (X11ICONN *) g_hash_table_lookup (_connections,
- GINT_TO_POINTER ((gint) call_data->connect_id));
- g_return_val_if_fail (conn != NULL, 0);
+ GINT_TO_POINTER ((gint) connect_id));
- g_list_foreach (conn->clients, _free_ic, NULL);
+ if (conn == NULL) {
+ return 0;
+ }
- g_list_free (conn->clients);
+ g_list_free_full (conn->clients, (GDestroyNotify) _free_ic);
g_hash_table_remove (_connections,
- GINT_TO_POINTER ((gint) call_data->connect_id));
+ GINT_TO_POINTER ((gint) connect_id));
g_slice_free (X11ICONN, conn);
return 1;
}
+static int
+xim_close (XIMS xims, IMCloseStruct *call_data)
+{
+ CARD16 connect_id = call_data->connect_id;
+
+ LOG (1, "XIM_CLOSE connect_id=%d", connect_id);
+
+ return _free_x11_iconn_from_id (connect_id);
+}
+
+static int
+xim_disconnect_ic (XIMS xims, IMDisConnectStruct *call_data)
+{
+ CARD16 connect_id = call_data->connect_id;
+
+ LOG (1, "XIM_DISCONNECT connect_id=%d", connect_id);
+
+ _free_x11_iconn_from_id (connect_id);
+
+ /* I am not sure if this can return 1 because I have not experienced
+ * that xim_disconnect_ic() is called. But I wish connect_id is
+ * released from _connections to avoid SEGV. */
+ return 0;
+}
+
static void
_xim_set_cursor_location (X11IC *x11ic)
@@ -745,6 +775,8 @@ ims_protocol_handler (XIMS xims, IMProtocol *call_data)
return xim_open (xims, (IMOpenStruct *)call_data);
case XIM_CLOSE:
return xim_close (xims, (IMCloseStruct *)call_data);
+ case XIM_DISCONNECT:
+ return xim_disconnect_ic (xims, (IMDisConnectStruct *)call_data);
case XIM_CREATE_IC:
return xim_create_ic (xims, (IMChangeICStruct *)call_data);
case XIM_DESTROY_IC: