From 90bc1aa27cd4c4b1e4fa8a1feba17e5435b9210a Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Thu, 3 Jan 2013 06:56:42 +0000 Subject: [PATCH] fix ecore-con client double-free case SVN revision: 82042 --- ChangeLog | 4 ++ NEWS | 1 + src/lib/ecore_con/ecore_con.c | 82 ++++++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e3b0ac932..49ab13b003 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-01-03 Carsten Haitzler (The Rasterman) + + * Fixed ecore_con case where freeing server double-frees clients + 2013-01-03 Jérémy Zurcher * Add eio_eet_sync symbols. diff --git a/NEWS b/NEWS index ecaa318386..595292b8f6 100644 --- a/NEWS +++ b/NEWS @@ -98,3 +98,4 @@ Fixes: * eio functions no longer crash when passed NULL and throw errors accordingly * Fix eina_xattr_value_ls() and eina_xattr_value_fd_ls() * Fix mask write lines to not choose too small segments + * Fix ecore_con case where freeing server double-frees clients diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c index c7e47bbef3..aaa880e32f 100644 --- a/src/lib/ecore_con/ecore_con.c +++ b/src/lib/ecore_con/ecore_con.c @@ -2364,15 +2364,23 @@ _ecore_con_event_client_add_free(Ecore_Con_Server *svr, e = ev; if (e->client) { + Eina_Bool svrfreed = EINA_FALSE; + e->client->event_count = eina_list_remove(e->client->event_count, e); if (e->client->host_server) { e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, ev); if ((!svr->event_count) && (svr->delete_me)) - _ecore_con_server_free(svr); + { + _ecore_con_server_free(svr); + svrfreed = EINA_TRUE; + } + } + if (!svrfreed) + { + if ((!e->client->event_count) && (e->client->delete_me)) + ecore_con_client_del(e->client); } - if ((!e->client->event_count) && (e->client->delete_me)) - ecore_con_client_del(e->client); } ecore_con_event_client_add_free(e); @@ -2390,15 +2398,23 @@ _ecore_con_event_client_del_free(Ecore_Con_Server *svr, e = ev; if (e->client) { + Eina_Bool svrfreed = EINA_FALSE; + e->client->event_count = eina_list_remove(e->client->event_count, e); if (e->client->host_server) { e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, ev); if ((!svr->event_count) && (svr->delete_me)) - _ecore_con_server_free(svr); + { + _ecore_con_server_free(svr); + svrfreed = EINA_TRUE; + } + } + if (!svrfreed) + { + if (!e->client->event_count) + _ecore_con_client_free(e->client); } - if (!e->client->event_count) - _ecore_con_client_free(e->client); } ecore_con_event_client_del_free(e); _ecore_con_event_count--; @@ -2412,18 +2428,26 @@ _ecore_con_event_client_write_free(Ecore_Con_Server *svr, { if (e->client) { + Eina_Bool svrfreed = EINA_FALSE; + e->client->event_count = eina_list_remove(e->client->event_count, e); if (e->client->host_server) { e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, e); if ((!svr->event_count) && (svr->delete_me)) - _ecore_con_server_free(svr); + { + _ecore_con_server_free(svr); + svrfreed = EINA_TRUE; + } + } + if (!svrfreed) + { + if (((!e->client->event_count) && (e->client->delete_me)) || + ((e->client->host_server && + ((e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP || + (e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST)))) + ecore_con_client_del(e->client); } - if (((!e->client->event_count) && (e->client->delete_me)) || - ((e->client->host_server && - ((e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP || - (e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST)))) - ecore_con_client_del(e->client); } ecore_con_event_client_write_free(e); _ecore_con_event_count--; @@ -2440,18 +2464,26 @@ _ecore_con_event_client_data_free(Ecore_Con_Server *svr, e = ev; if (e->client) { + Eina_Bool svrfreed = EINA_FALSE; + e->client->event_count = eina_list_remove(e->client->event_count, e); if (e->client->host_server) { e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, ev); } if ((!svr->event_count) && (svr->delete_me)) - _ecore_con_server_free(svr); - if (((!e->client->event_count) && (e->client->delete_me)) || - ((e->client->host_server && - ((e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP || - (e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST)))) - ecore_con_client_del(e->client); + { + _ecore_con_server_free(svr); + svrfreed = EINA_TRUE; + } + if (!svrfreed) + { + if (((!e->client->event_count) && (e->client->delete_me)) || + ((e->client->host_server && + ((e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP || + (e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST)))) + ecore_con_client_del(e->client); + } } free(e->data); ecore_con_event_client_data_free(e); @@ -2558,15 +2590,23 @@ _ecore_con_event_client_error_free(Ecore_Con_Server *svr, Ecore_Con_Event_Client { if (e->client) { + Eina_Bool svrfreed = EINA_FALSE; + if (eina_list_data_find(svr->clients, e->client)) { e->client->event_count = eina_list_remove(e->client->event_count, e); if ((!e->client->event_count) && (e->client->delete_me)) - _ecore_con_client_free(e->client); + { + _ecore_con_client_free(e->client); + svrfreed = EINA_TRUE; + } } svr->event_count = eina_list_remove(svr->event_count, e); - if ((!svr->event_count) && (svr->delete_me)) - _ecore_con_server_free(svr); + if (!svrfreed) + { + if ((!svr->event_count) && (svr->delete_me)) + _ecore_con_server_free(svr); + } } free(e->error); ecore_con_event_client_error_free(e);