forked from enlightenment/efl
eldbus: make connections fork-safe
after a fork, any existing connection objects can no longer be used, but it's up to the user to destroy them. internally, this prevents existing connections from ever being returned as valid connections and creates new ones after a fork also destroy fd handlers for connections to ensure that no data is accidentally clobbered before the connections are cleaned up
This commit is contained in:
parent
10ce0cbd8a
commit
95a339733a
|
@ -85,6 +85,45 @@ static void _eldbus_connection_context_event_cb_del(Eldbus_Connection_Context_Ev
|
|||
static void eldbus_dispatch_name_owner_change(Eldbus_Connection_Name *cn, const char *old_id);
|
||||
static void _eldbus_connection_free(Eldbus_Connection *conn);
|
||||
|
||||
static void
|
||||
eldbus_fd_handler_del(Eldbus_Handler_Data *hd)
|
||||
{
|
||||
if (!hd->fd_handler) return;
|
||||
|
||||
DBG("free Eldbus_Handler_Data %d", hd->fd);
|
||||
hd->conn->fd_handlers = eina_inlist_remove(hd->conn->fd_handlers,
|
||||
EINA_INLIST_GET(hd));
|
||||
if (hd->fd_handler)
|
||||
{
|
||||
ecore_main_fd_handler_del(hd->fd_handler);
|
||||
hd->fd_handler = NULL;
|
||||
}
|
||||
|
||||
free(hd);
|
||||
}
|
||||
|
||||
static void
|
||||
_eldbus_fork_reset()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i =0; i < ELDBUS_CONNECTION_TYPE_LAST - 1; i++)
|
||||
{
|
||||
Eldbus_Connection *conn = shared_connections[i];
|
||||
if (conn)
|
||||
{
|
||||
Eina_Inlist *list;
|
||||
Eldbus_Handler_Data *fd_handler;
|
||||
|
||||
EINA_INLIST_FOREACH_SAFE(conn->fd_handlers, list, fd_handler)
|
||||
dbus_watch_set_data(fd_handler->watch, NULL, NULL);
|
||||
}
|
||||
shared_connections[i] = NULL;
|
||||
}
|
||||
if (address_connections) eina_hash_free(address_connections);
|
||||
address_connections = NULL;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
eldbus_init(void)
|
||||
{
|
||||
|
@ -131,7 +170,7 @@ eldbus_init(void)
|
|||
if (!eldbus_object_init()) goto object_failed;
|
||||
if (!eldbus_proxy_init()) goto proxy_failed;
|
||||
if (!eldbus_service_init()) goto service_failed;
|
||||
|
||||
ecore_fork_reset_callback_add(_eldbus_fork_reset, NULL);
|
||||
return _eldbus_init_count;
|
||||
|
||||
service_failed:
|
||||
|
@ -205,6 +244,7 @@ eldbus_shutdown(void)
|
|||
if (--_eldbus_init_count)
|
||||
return _eldbus_init_count;
|
||||
|
||||
ecore_fork_reset_callback_del(_eldbus_fork_reset, NULL);
|
||||
if (shared_connections[ELDBUS_CONNECTION_TYPE_SESSION - 1])
|
||||
{
|
||||
CRI("Alive TYPE_SESSION connection");
|
||||
|
@ -548,24 +588,6 @@ eldbus_connection_name_object_get(Eldbus_Connection *conn, const char *name, con
|
|||
return eina_hash_find(cn->objects, path);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
eldbus_fd_handler_del(Eldbus_Handler_Data *hd)
|
||||
{
|
||||
if (!hd->fd_handler) return;
|
||||
|
||||
DBG("free Eldbus_Handler_Data %d", hd->fd);
|
||||
hd->conn->fd_handlers = eina_inlist_remove(hd->conn->fd_handlers,
|
||||
EINA_INLIST_GET(hd));
|
||||
if (hd->fd_handler)
|
||||
{
|
||||
ecore_main_fd_handler_del(hd->fd_handler);
|
||||
hd->fd_handler = NULL;
|
||||
}
|
||||
|
||||
free(hd);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
eldbus_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
||||
{
|
||||
|
@ -1256,7 +1278,10 @@ _eldbus_connection_free(Eldbus_Connection *conn)
|
|||
if (conn->type && conn->shared)
|
||||
{
|
||||
if (conn->type == ELDBUS_CONNECTION_TYPE_ADDRESS)
|
||||
eina_hash_del_by_data(address_connections, conn);
|
||||
{
|
||||
if (address_connections)
|
||||
eina_hash_del_by_data(address_connections, conn);
|
||||
}
|
||||
else if (shared_connections[conn->type - 1] == (void *) conn)
|
||||
shared_connections[conn->type - 1] = NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue