summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com-core.c58
-rw-r--r--src/com-core_thread.c29
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;
}