diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com-core.c | 58 | ||||
-rw-r--r-- | src/com-core_thread.c | 29 |
2 files changed, 60 insertions, 27 deletions
diff --git a/src/com-core.c b/src/com-core.c index 68793b9..5869ba9 100644 --- a/src/com-core.c +++ b/src/com-core.c @@ -40,6 +40,7 @@ static struct { struct dlist *watch_list; struct dlist *conn_cb_list; struct dlist *disconn_cb_list; + struct dlist *disconn_fd_list; enum processing_event_callback { PROCESSING_NONE = 0x0, PROCESSING_DISCONNECTION = 0x01, @@ -49,6 +50,7 @@ static struct { .watch_list = NULL, .conn_cb_list = NULL, .disconn_cb_list = NULL, + .disconn_fd_list = NULL, .processing_event_callback = PROCESSING_NONE, }; @@ -127,13 +129,18 @@ static void watch_item_destroy_all(int socket_fd) dlist_foreach_safe(s_info.watch_list, l, n, item) { if (item->server_fd == socket_fd) { DbgPrint("Watch item removed: %d/%d\n", item->server_fd, item->fd); - /*! - * \WARN + /** + * @WARN * If the watch_list item is removed from disconnected * callback, this list loop can be broken. * Please check it again. */ - invoke_disconn_cb_list(item->fd, 0, 0, 0); + (void)invoke_disconn_cb_list(item->fd, 0, 0, 0); + /** + * @note + * socket_fd will be closed by caller. + * so we do not need to close it at here. + */ s_info.watch_list = dlist_remove(s_info.watch_list, l); if (item->id > 0) { @@ -172,16 +179,34 @@ HAPI void invoke_con_cb_list(int server_fd, int handle, guint id, void *data, in s_info.processing_event_callback &= ~PROCESSING_CONNECTION; } -HAPI void invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch) +HAPI int invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch) { struct dlist *l; struct dlist *n; struct evtdata *cbdata; + void *item; + + /** + * @note + * Basically, the disconnected handler will be called once. + * But from the disconnected callback, someone calls fini(fd), + * this disconnection callback can be called again. + * So we have to check whether this is a nested call or not. + * If it is a nested call, we should not do anything anymore. + */ + dlist_foreach_safe(s_info.disconn_fd_list, l, n, item) { + if (handle == (int)((long)item)) { /*!< Cast for 64 bits */ + DbgPrint("nested destroyer %d\n", handle); + return 1; + } + } + + s_info.disconn_fd_list = dlist_append(s_info.disconn_fd_list, (void *)((long)handle)); /*!< Cast for 64 bits */ s_info.processing_event_callback |= PROCESSING_DISCONNECTION; dlist_foreach_safe(s_info.disconn_cb_list, l, n, cbdata) { - /*! - * \NOTE + /** + * @note * cbdata->deleted must has to be checked before call the function and * return from the function call. */ @@ -197,6 +222,9 @@ HAPI void invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int ErrPrint("Failed to destroy watch item\n"); } } + + dlist_remove_data(s_info.disconn_fd_list, (void *)((long)handle)); /*!< Cast for 64 bits */ + return 0; } static int validate_handle(int fd) @@ -223,14 +251,14 @@ static gboolean client_cb(GIOChannel *src, GIOCondition cond, gpointer data) if (!(cond & G_IO_IN)) { DbgPrint("Client is disconencted\n"); - invoke_disconn_cb_list(client_fd, 0, 1, 1); + (void)invoke_disconn_cb_list(client_fd, 0, 1, 1); secure_socket_destroy_handle(client_fd); return FALSE; } if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) { DbgPrint("Client connection is lost\n"); - invoke_disconn_cb_list(client_fd, 0, 1, 1); + (void)invoke_disconn_cb_list(client_fd, 0, 1, 1); secure_socket_destroy_handle(client_fd); return FALSE; } @@ -238,14 +266,14 @@ static gboolean client_cb(GIOChannel *src, GIOCondition cond, gpointer data) ret = cbdata->service_cb(client_fd, cbdata->data); if (ret < 0) { DbgPrint("service callback returns %d < 0\n", ret); - invoke_disconn_cb_list(client_fd, 0, 1, 1); + (void)invoke_disconn_cb_list(client_fd, 0, 1, 1); secure_socket_destroy_handle(client_fd); return FALSE; } /* Check whether the socket FD is closed or not */ if (!validate_handle(client_fd)) { - invoke_disconn_cb_list(client_fd, 0, 1, 1); + (void)invoke_disconn_cb_list(client_fd, 0, 1, 1); secure_socket_destroy_handle(client_fd); return FALSE; } @@ -736,16 +764,18 @@ EAPI void *com_core_del_event_callback(enum com_core_event_type type, int (*cb)( EAPI int com_core_server_destroy(int handle) { DbgPrint("Close server handle[%d]\n", handle); - invoke_disconn_cb_list(handle, 1, 1, 1); - secure_socket_destroy_handle(handle); + if (invoke_disconn_cb_list(handle, 1, 1, 1) == 0) { + secure_socket_destroy_handle(handle); + } return 0; } EAPI int com_core_client_destroy(int handle) { DbgPrint("Close client handle[%d]\n", handle); - invoke_disconn_cb_list(handle, 1, 1, 1); - secure_socket_destroy_handle(handle); + if (invoke_disconn_cb_list(handle, 1, 1, 1) == 0) { + secure_socket_destroy_handle(handle); + } return 0; } diff --git a/src/com-core_thread.c b/src/com-core_thread.c index 42a3cbd..3bb457f 100644 --- a/src/com-core_thread.c +++ b/src/com-core_thread.c @@ -189,7 +189,7 @@ static inline void terminate_thread(struct tcb *tcb) if (status != 0) { ErrPrint("Join: %s\n", strerror(status)); } else { - ErrPrint("Thread returns: %d\n", (int)res); + ErrPrint("Thread returns: %d\n", (int)((long)res)); } dlist_foreach_safe(tcb->chunk_list, l, n, chunk) { @@ -503,7 +503,7 @@ static gboolean evt_pipe_cb(GIOChannel *src, GIOCondition cond, gpointer data) errout: DbgPrint("Disconnecting\n"); - invoke_disconn_cb_list(tcb->handle, 0, 0, 0); + (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0); terminate_thread(tcb); tcb_destroy(tcb); return FALSE; @@ -672,7 +672,7 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data) } if (ret != 0) { ErrPrint("Thread creation failed: %s\n", strerror(ret)); - invoke_disconn_cb_list(tcb->handle, 0, 0, 0); + (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0); secure_socket_destroy_handle(tcb->handle); tcb_destroy(tcb); server_destroy(server); @@ -770,7 +770,7 @@ EAPI int com_core_thread_client_create(const char *addr, int is_sync, int (*serv } if (ret != 0) { ErrPrint("Thread creation failed: %s\n", strerror(ret)); - invoke_disconn_cb_list(tcb->handle, 0, 0, 0); + (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0); secure_socket_destroy_handle(tcb->handle); tcb_destroy(tcb); return -EFAULT; @@ -876,7 +876,7 @@ EAPI int com_core_thread_client_create_by_fd(int client_fd, int is_sync, int (*s } if (ret != 0) { ErrPrint("Thread creation failed: %s\n", strerror(ret)); - invoke_disconn_cb_list(tcb->handle, 0, 0, 0); + (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0); secure_socket_destroy_handle(tcb->handle); tcb_destroy(tcb); return -EFAULT; @@ -1151,9 +1151,10 @@ EAPI int com_core_thread_server_destroy(int handle) continue; } - invoke_disconn_cb_list(handle, 0, 0, 0); - terminate_thread(tcb); - tcb_destroy(tcb); + if (invoke_disconn_cb_list(handle, 0, 0, 0) == 0) { + terminate_thread(tcb); + tcb_destroy(tcb); + } return 0; } @@ -1162,8 +1163,9 @@ EAPI int com_core_thread_server_destroy(int handle) continue; } - invoke_disconn_cb_list(handle, 0, 0, 0); - server_destroy(server); + if (invoke_disconn_cb_list(handle, 0, 0, 0) == 0) { + server_destroy(server); + } return 0; } @@ -1183,9 +1185,10 @@ EAPI int com_core_thread_client_destroy(int handle) return -ENOENT; } - invoke_disconn_cb_list(handle, 0, 0, 0); - terminate_thread(tcb); - tcb_destroy(tcb); + if (invoke_disconn_cb_list(handle, 0, 0, 0) == 0) { + terminate_thread(tcb); + tcb_destroy(tcb); + } return 0; } |