} tts_tidl_info_s;
static GList* g_tidl_infos = NULL;
+static GSList *g_destruction_scheduled_handles = NULL;
+
+static Ecore_Idler *g_destroy_handles_idler = NULL;
static tts_tidl_info_s* __get_tidl_info_s(unsigned int uid)
RETM_IF(NULL == client, "[ERROR] Fail to get client");
unsigned int u_uid = (unsigned int)uid;
+ if (NULL != g_slist_find(g_destruction_scheduled_handles, user_data)) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] This message is for destroyed handle.");
+ return;
+ }
+
SLOG(LOG_DEBUG, TAG_TTSC, "__notify_cb is invoked pid(%d) uid(%u)", pid, u_uid);
bundle_get_str(msg, TTS_BUNDLE_METHOD, &method);
return TTS_ERROR_NONE;
}
-static inline int __destroy_rpc_port(tts_tidl_info_s* info)
+static void destroy_scheduled_handle(gpointer data)
+{
+ rpc_port_proxy_tts_h rpc_h = (rpc_port_proxy_tts_h)data;
+ int ret = rpc_port_proxy_tts_destroy(rpc_h);
+ if (RPC_PORT_ERROR_NONE != ret) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy handle. ret(%d/%s)", ret, get_error_message(ret));
+ }
+}
+
+static Eina_Bool destroy_scheduled_handles_by_ecore_idler(void *user_data)
{
- RETVM_IF(NULL == info->rpc_h, TTS_ERROR_NONE, "[TIDL] Handle is already destroyed");
+ SLOG(LOG_INFO, TAG_TTSC, "[INFO] Destroy RPC handles those are scheduled to be destroyed.");
+ g_slist_free_full(g_destruction_scheduled_handles, destroy_scheduled_handle);
+ g_destruction_scheduled_handles = NULL;
+ g_destroy_handles_idler = NULL;
- if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_destroy(info->rpc_h)) {
- SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy handle");
- return TTS_ERROR_OPERATION_FAILED;
+ return EINA_FALSE;
+}
+
+static inline void destroy_rpc_port(tts_tidl_info_s* info)
+{
+ RETM_IF(NULL == info->rpc_h, "[TIDL] Handle is already destroyed");
+
+ g_destruction_scheduled_handles = g_slist_append(g_destruction_scheduled_handles, info->rpc_h);
+ if (NULL == g_destroy_handles_idler) {
+ g_destroy_handles_idler = ecore_idler_add(destroy_scheduled_handles_by_ecore_idler, NULL);
}
+
info->rpc_h = NULL;
info->notify_cb_h = NULL;
info->register_callback_invoked = false;
info->connection_requesting = false;
info->connected = false;
-
- return TTS_ERROR_NONE;
}
int tts_tidl_close_connection(unsigned int uid)
tts_tidl_info_s* info = __get_tidl_info_s(uid);
RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
- if (TTS_ERROR_NONE != __destroy_rpc_port(info)) {
- SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to disconnect");
- return TTS_ERROR_OPERATION_FAILED;
+ destroy_rpc_port(info);
+ if (g_destroy_handles_idler) {
+ ecore_idler_del(g_destroy_handles_idler);
+ g_destroy_handles_idler = NULL;
}
+ g_slist_free_full(g_destruction_scheduled_handles, destroy_scheduled_handle);
+ g_destruction_scheduled_handles = NULL;
+
free(info->engine_app_id);
info->engine_app_id = NULL;
return TTS_ERROR_OUT_OF_MEMORY;
}
- rpc_port_proxy_tts_notify_cb_set_callback(info->notify_cb_h, __notify_cb, NULL);
+ rpc_port_proxy_tts_notify_cb_set_callback(info->notify_cb_h, __notify_cb, (void *)info->rpc_h);
rpc_port_proxy_tts_notify_cb_set_once(info->notify_cb_h, false);
return TTS_ERROR_NONE;
static int __reset_rpc_port(tts_tidl_info_s* info, const char* engine_id)
{
- if (TTS_ERROR_NONE != __destroy_rpc_port(info)) {
- SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy old rpc port");
- return TTS_ERROR_OPERATION_FAILED;
- }
+ destroy_rpc_port(info);
if (TTS_ERROR_NONE != __create_rpc_port(info, engine_id)) {
SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create new rpc port");
switch (ret) {
case RPC_PORT_ERROR_IO_ERROR:
SLOG(LOG_INFO, TAG_TTSC, "[INFO] IO error occurs. Destroy old rpc port");
- __destroy_rpc_port(info);
+ destroy_rpc_port(info);
return TTS_ERROR_IO_ERROR;
case RPC_PORT_ERROR_OUT_OF_MEMORY:
}
tts_client_set_start_listening(uid, false);
- if (TTS_ERROR_NONE != __destroy_rpc_port(info)) {
- SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy rpc port. ret(%d)", ret);
- return TTS_ERROR_OPERATION_FAILED;
- }
+ destroy_rpc_port(info);
SLOG(LOG_ERROR, TAG_TTSC, ">>>> Success tts finalize. uid(%u)", uid);
return TTS_ERROR_NONE;