Do not process the finalize in the nested call. tizen accepted/tizen/mobile/20150917.041057 accepted/tizen/tv/20150917.041120 submit/tizen/20150916.141025 submit/tizen/20150917.014254 submit/tizen_common/20151015.190624 submit/tizen_common/20151019.135620 tizen_3.0.m2.a1_mobile_release tizen_3.0.m2.a1_tv_release
authorSung-jae Park <nicesj.park@samsung.com>
Tue, 4 Aug 2015 07:32:25 +0000 (16:32 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Tue, 4 Aug 2015 07:32:25 +0000 (16:32 +0900)
Change-Id: I056b5953cff53c6053412b56c6be4a31aa7c33ba

include/com-core_internal.h
packaging/libcom-core.spec
src/com-core.c
src/com-core_thread.c

index 667a48d..dc5591b 100644 (file)
 */
 
 extern void invoke_con_cb_list(int server_fd, int handle, guint id, void *data, int watch);
-extern void invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch);
+
+/**
+ * @note
+ * This function will returns 0 if it is processed peacefully,
+ * But 1 will be returned if it is already called. (in case of the nested call)
+ */
+extern int invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch);
 
 /* End of a file */
index 0ff41a3..a1d1a48 100644 (file)
@@ -1,6 +1,6 @@
 Name: libcom-core
-Summary: Library for the light-weight IPC 
-Version: 1.0.1
+Summary: Library for the light-weight IPC
+Version: 1.0.2
 Release: 1
 Group: Base/IPC
 License: Apache-2.0
index 68793b9..5869ba9 100644 (file)
@@ -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;
 }
 
index 42a3cbd..3bb457f 100644 (file)
@@ -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;
 }