diff --git a/src/ui/core.c b/src/ui/core.c index 24e15eba..39535eaa 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -712,6 +712,8 @@ ui_close_win(int index) } } + // remove the IQ handlers + iq_handlers_remove_win(window); wins_close_by_num(index); title_bar_console(); status_bar_current(1); diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 793dbc59..924c98be 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -267,6 +267,54 @@ iq_handlers_init(void) rooms_cache = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)xmpp_stanza_release); } +struct iq_win_finder +{ + gsize max, cur; + char** to_be_removed; +}; + +static void +_win_find(char* key, + ProfIqHandler* handler, + struct iq_win_finder* finder) +{ + if (handler->func == _mam_rsm_id_handler) { + if (finder->cur >= finder->max) { + finder->max *= 2; + finder->to_be_removed = g_realloc_n(finder->to_be_removed, finder->max, sizeof(char*)); + } + finder->to_be_removed[finder->cur++] = g_strdup(key); + } +} + +void +iq_handlers_remove_win(ProfWin* window) +{ + log_debug("Remove window %p of type %d", window, window ? window->type : -1); + if (!window) + return; + GSList *cur = late_delivery_windows, *next; + while (cur) { + LateDeliveryUserdata* del_data = cur->data; + next = g_slist_next(cur); + if (del_data->win == (void*)window) + late_delivery_windows = g_slist_delete_link(late_delivery_windows, + cur); + cur = next; + } + struct iq_win_finder st = { 0 }; + st.max = g_hash_table_size(id_handlers); + if (st.max == 0) + return; + st.to_be_removed = g_new(char*, st.max); + g_hash_table_foreach(id_handlers, (GHFunc)_win_find, &st); + for (gsize n = 0; n < st.cur; ++n) { + g_hash_table_remove(id_handlers, st.to_be_removed[n]); + g_free(st.to_be_removed[n]); + } + g_free(st.to_be_removed); +} + void iq_handlers_clear() { @@ -2696,6 +2744,10 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) gboolean is_complete = g_strcmp0(xmpp_stanza_get_attribute(fin, "complete"), "true") == 0; MamRsmUserdata* data = (MamRsmUserdata*)userdata; ProfWin* window = (ProfWin*)data->win; + if (wins_get_num(window) == -1) { + log_error("Window %p should not get any events anymore", window); + return 0; + } buffer_remove_entry(window->layout->buffer, 0); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index baff1295..23b20729 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -240,6 +240,7 @@ void iq_enable_carbons(void); void iq_disable_carbons(void); void iq_send_software_version(const char* const fulljid); void iq_rooms_cache_clear(void); +void iq_handlers_remove_win(ProfWin* window); void iq_handlers_clear(); void iq_room_list_request(gchar* conferencejid, gchar* filter); void iq_disco_info_request(gchar* jid);