From 1587551badffecface1718d0d941ee81777d45a7 Mon Sep 17 00:00:00 2001 From: raster Date: Thu, 24 May 2012 07:49:30 +0000 Subject: [PATCH] and no more segv's in ecore-con and ecore-ipc. see changelog. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@71400 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- ChangeLog | 10 ++++++++ src/lib/ecore_con/Ecore_Con.h | 22 ++++++++++++++++- src/lib/ecore_con/ecore_con.c | 46 ++++++++++++++++++++++++++++------- src/lib/ecore_con/ecore_con_private.h | 1 + src/lib/ecore_ipc/ecore_ipc.c | 3 ++- 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6be42be..e997a78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -662,3 +662,13 @@ 2012-05-24 Doyoun Kang * Add Ecore_X_Error_Code enumeration in ecore_x + +2012-05-24 Carsten Haitzler (The Rasterman) + + * Add ecore_con_client_ref() and ecore_con_client_unref() + * Fix ecore_con to obey reference counting for con clients + * Fix lurking bug in ecore_ipc that had it be able to crash in + accessind already deleted ecore-con clients. use client + ref/unref to fix it. No backport of this fix as it requires a + new feature. + diff --git a/src/lib/ecore_con/Ecore_Con.h b/src/lib/ecore_con/Ecore_Con.h index 9784adf..7fe8495 100644 --- a/src/lib/ecore_con/Ecore_Con.h +++ b/src/lib/ecore_con/Ecore_Con.h @@ -1240,7 +1240,27 @@ EAPI Eina_Bool ecore_con_client_connected_get(Ecore_Con_Client *cl); * Use this function to return the port on which a given client has connected. */ EAPI int ecore_con_client_port_get(Ecore_Con_Client *cl); - +/** + * @brief increment the references on a connection client + * + * @param cl The client + * This increases the references on the given client to keep it alive in + * memory for longer until all references are release by + * ecore_con_client_unref(). + * @since 1.3 + */ +EAPI void ecore_con_client_ref(Ecore_Con_Client *cl); +/** + * @brief decrement the references on a connection client + * + * @param cl The client + * This decrements the references on the given client and once references hit + * 0, the client is deleted. ecore_con_client_del() does the same thing as + * ecore_con_client_unref(). All con clients start with a reference count of + * 1. + * @since 1.3 + */ +EAPI void ecore_con_client_unref(Ecore_Con_Client *cl); /** diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c index 33f8342..5ba6624 100644 --- a/src/lib/ecore_con/ecore_con.c +++ b/src/lib/ecore_con/ecore_con.c @@ -116,9 +116,12 @@ _ecore_con_client_kill(Ecore_Con_Client *cl) } INF("Lost client %s", (cl->ip) ? cl->ip : ""); if (cl->fd_handler) - ecore_main_fd_handler_del(cl->fd_handler); - - cl->fd_handler = NULL; + { + ecore_main_fd_handler_del(cl->fd_handler); + cl->fd_handler = NULL; + } + if (cl->ref <= 0) + _ecore_con_client_free(cl); } void @@ -130,9 +133,10 @@ _ecore_con_server_kill(Ecore_Con_Server *svr) ecore_con_event_server_del(svr); if (svr->fd_handler) - ecore_main_fd_handler_del(svr->fd_handler); - - svr->fd_handler = NULL; + { + ecore_main_fd_handler_del(svr->fd_handler); + svr->fd_handler = NULL; + } } #define _ecore_con_server_kill(svr) do { \ @@ -867,12 +871,35 @@ ecore_con_client_del(Ecore_Con_Client *cl) ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_del"); return NULL; } - - _ecore_con_client_kill(cl); + ecore_con_client_unref(cl); return cl->data; } EAPI void +ecore_con_client_ref(Ecore_Con_Client *cl) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_ref"); + return; + } + cl->ref++; +} + +EAPI void +ecore_con_client_unref(Ecore_Con_Client *cl) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_unref"); + return; + } + cl->ref--; + if (cl->ref <= 0) + _ecore_con_client_kill(cl); +} + +EAPI void ecore_con_client_data_set(Ecore_Con_Client *cl, const void *data) { @@ -1834,6 +1861,7 @@ _ecore_con_svr_tcp_handler(void *data, return ECORE_CALLBACK_RENEW; } cl->host_server = svr; + cl->ref = 1; client_addr_len = sizeof(client_addr); memset(&client_addr, 0, client_addr_len); @@ -2383,7 +2411,7 @@ _ecore_con_event_client_del_free(Ecore_Con_Server *svr, _ecore_con_server_free(svr); } if (!e->client->event_count) - _ecore_con_client_free(e->client); + ecore_con_client_del(e->client); } ecore_con_event_client_del_free(e); _ecore_con_event_count--; diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h index 4f8f792..e3b9adb 100644 --- a/src/lib/ecore_con/ecore_con_private.h +++ b/src/lib/ecore_con/ecore_con_private.h @@ -119,6 +119,7 @@ struct _Ecore_Con_Client SSL *ssl; int ssl_err; #endif + int ref; Ecore_Con_Ssl_State ssl_state; Eina_Bool handshaking : 1; Eina_Bool upgrade : 1; /* STARTTLS queued */ diff --git a/src/lib/ecore_ipc/ecore_ipc.c b/src/lib/ecore_ipc/ecore_ipc.c index 3518be2..54ee3ad 100644 --- a/src/lib/ecore_ipc/ecore_ipc.c +++ b/src/lib/ecore_ipc/ecore_ipc.c @@ -881,7 +881,7 @@ ecore_ipc_client_del(Ecore_Ipc_Client *cl) if (cl->event_count == 0) { svr = ecore_con_server_data_get(ecore_con_client_server_get(cl->client)); - ecore_con_client_del(cl->client); + ecore_con_client_unref(cl->client); svr->clients = eina_list_remove(svr->clients, cl); if (cl->buf) free(cl->buf); ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE); @@ -1034,6 +1034,7 @@ _ecore_ipc_event_client_add(void *data __UNUSED__, int ev_type __UNUSED__, void svr = ecore_con_server_data_get(ecore_con_client_server_get(e->client)); ECORE_MAGIC_SET(cl, ECORE_MAGIC_IPC_CLIENT); cl->client = e->client; + ecore_con_client_ref(cl->client); cl->max_buf_size = 32 * 1024; ecore_con_client_data_set(cl->client, (void *)cl); svr->clients = eina_list_append(svr->clients, cl); -- 2.7.4