summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSung-jae Park <nicesj.park@samsung.com>2014-05-22 11:18:22 +0900
committerSung-jae Park <nicesj.park@samsung.com>2014-05-22 11:18:22 +0900
commit960f0342ab2ade392af7a7d6234344e27fa76fd1 (patch)
tree21728d052b58472b988266ec57a45e1df2839581
parent91ba80b04e61e8e689b9757cd337c4c5c8fc3c6a (diff)
downloadcom-core-960f0342ab2ade392af7a7d6234344e27fa76fd1.tar.gz
com-core-960f0342ab2ade392af7a7d6234344e27fa76fd1.tar.bz2
com-core-960f0342ab2ade392af7a7d6234344e27fa76fd1.zip
Clean up all resource for non-threaded IPC.
Change-Id: I50c9f6f02580d8390307045278fdef0999a65cbb
-rw-r--r--include/com-core_internal.h4
-rw-r--r--packaging/libcom-core.spec2
-rw-r--r--src/com-core.c163
-rw-r--r--src/com-core_thread.c17
4 files changed, 158 insertions, 28 deletions
diff --git a/include/com-core_internal.h b/include/com-core_internal.h
index 1523d05..667a48d 100644
--- a/include/com-core_internal.h
+++ b/include/com-core_internal.h
@@ -15,7 +15,7 @@
*
*/
-extern void invoke_con_cb_list(int handle);
-extern void invoke_disconn_cb_list(int handle);
+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);
/* End of a file */
diff --git a/packaging/libcom-core.spec b/packaging/libcom-core.spec
index 8e27d57..e56cc20 100644
--- a/packaging/libcom-core.spec
+++ b/packaging/libcom-core.spec
@@ -1,6 +1,6 @@
Name: libcom-core
Summary: Library for the light-weight IPC
-Version: 0.5.9
+Version: 0.5.10
Release: 1
Group: Base/IPC
License: Apache-2.0
diff --git a/src/com-core.c b/src/com-core.c
index d254014..f1973f7 100644
--- a/src/com-core.c
+++ b/src/com-core.c
@@ -37,6 +37,7 @@
#include "util.h"
static struct {
+ struct dlist *watch_list;
struct dlist *conn_cb_list;
struct dlist *disconn_cb_list;
enum processing_event_callback {
@@ -45,11 +46,19 @@ static struct {
PROCESSING_CONNECTION = 0x02,
} processing_event_callback;
} s_info = {
+ .watch_list = NULL,
.conn_cb_list = NULL,
.disconn_cb_list = NULL,
.processing_event_callback = PROCESSING_NONE,
};
+struct watch_item {
+ int server_fd;
+ int fd;
+ guint id;
+ void *cbdata;
+};
+
struct cbdata {
int (*service_cb)(int fd, void *data);
void *data;
@@ -61,12 +70,93 @@ struct evtdata {
void *data;
};
-HAPI void invoke_con_cb_list(int handle)
+static int watch_item_create(int server_fd, int handle, guint id, void *cbdata)
+{
+ struct watch_item *item;
+
+ item = malloc(sizeof(*item));
+ if (!item) {
+ return -ENOMEM;
+ }
+
+ item->server_fd = server_fd;
+ item->fd = handle;
+ item->id = id;
+ item->cbdata = cbdata;
+
+ DbgPrint("Watch Item is created for %d/%d\n", server_fd, handle);
+ s_info.watch_list = dlist_append(s_info.watch_list, item);
+ return 0;
+}
+
+static int watch_item_destroy(int handle, int remove_id, int remove_cbdata)
+{
+ struct dlist *l;
+ struct dlist *n;
+ struct watch_item *item;
+
+ dlist_foreach_safe(s_info.watch_list, l, n, item) {
+ if (item->fd == handle) {
+ s_info.watch_list = dlist_remove(s_info.watch_list, l);
+
+ DbgPrint("Watch item is destroyed for %d/%d\n", item->server_fd, item->fd);
+
+ if (remove_id && item->id) {
+ g_source_remove(item->id);
+ }
+
+ if (remove_cbdata && item->cbdata) {
+ free(item->cbdata);
+ }
+
+ free(item);
+ return 0;
+ }
+ }
+
+ DbgPrint("No entry found\n");
+ return -ENOENT;
+}
+
+static void watch_item_destroy_all(int socket_fd)
+{
+ struct dlist *l;
+ struct dlist *n;
+ struct watch_item *item;
+
+ 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
+ * 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);
+
+ s_info.watch_list = dlist_remove(s_info.watch_list, l);
+ if (item->id > 0) {
+ g_source_remove(item->id);
+ }
+ free(item->cbdata);
+ free(item);
+ }
+ }
+}
+
+HAPI void invoke_con_cb_list(int server_fd, int handle, guint id, void *data, int watch)
{
struct dlist *l;
struct dlist *n;
struct evtdata *cbdata;
+ if (watch) {
+ if (watch_item_create(server_fd, handle, id, data) < 0) {
+ ErrPrint("Failed to create a watch item\n");
+ }
+ }
+
s_info.processing_event_callback |= PROCESSING_CONNECTION;
dlist_foreach_safe(s_info.conn_cb_list, l, n, cbdata) {
/*!
@@ -82,7 +172,7 @@ HAPI void invoke_con_cb_list(int handle)
s_info.processing_event_callback &= ~PROCESSING_CONNECTION;
}
-HAPI void invoke_disconn_cb_list(int handle)
+HAPI void invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch)
{
struct dlist *l;
struct dlist *n;
@@ -101,6 +191,12 @@ HAPI void invoke_disconn_cb_list(int handle)
}
}
s_info.processing_event_callback &= ~PROCESSING_DISCONNECTION;
+
+ if (watch) {
+ if (watch_item_destroy(handle, remove_id, remove_data) < 0) {
+ ErrPrint("Failed to destroy watch item\n");
+ }
+ }
}
static int validate_handle(int fd)
@@ -127,14 +223,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);
+ 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);
+ invoke_disconn_cb_list(client_fd, 0, 1, 1);
secure_socket_destroy_handle(client_fd);
return FALSE;
}
@@ -142,13 +238,19 @@ 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);
+ 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 */
- return validate_handle(client_fd) ? TRUE : FALSE;
+ if (!validate_handle(client_fd)) {
+ invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ secure_socket_destroy_handle(client_fd);
+ return FALSE;
+ }
+
+ return TRUE;
}
static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
@@ -161,6 +263,7 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
socket_fd = g_io_channel_unix_get_fd(src);
if (!(cond & G_IO_IN)) {
ErrPrint("Accept socket closed\n");
+ watch_item_destroy_all(socket_fd);
secure_socket_destroy_handle(socket_fd);
free(cbdata);
return FALSE;
@@ -168,6 +271,7 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
ErrPrint("Client connection is lost\n");
+ watch_item_destroy_all(socket_fd);
secure_socket_destroy_handle(socket_fd);
free(cbdata);
return FALSE;
@@ -175,8 +279,8 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
client_fd = secure_socket_get_connection_handle(socket_fd);
if (client_fd < 0) {
- free(cbdata);
- return FALSE;
+ /* Keep server running */
+ return TRUE;
}
DbgPrint("New connectino arrived: server(%d), client(%d)\n", socket_fd, client_fd);
@@ -192,8 +296,8 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
if (!gio) {
ErrPrint("Failed to get gio\n");
secure_socket_destroy_handle(client_fd);
- free(cbdata);
- return FALSE;
+ /* Keep server running */
+ return TRUE;
}
g_io_channel_set_close_on_unref(gio, FALSE);
@@ -201,6 +305,7 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)client_cb, cbdata);
if (id <= 0) {
GError *err = NULL;
+
ErrPrint("Failed to add IO watch\n");
g_io_channel_shutdown(gio, TRUE, &err);
if (err) {
@@ -209,14 +314,21 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
}
g_io_channel_unref(gio);
secure_socket_destroy_handle(client_fd);
- free(cbdata);
- return FALSE;
+ /* Keep server running */
+ return TRUE;
}
g_io_channel_unref(gio);
- invoke_con_cb_list(client_fd);
- return validate_handle(socket_fd) ? TRUE : FALSE;
+ invoke_con_cb_list(socket_fd, client_fd, id, NULL, 1);
+
+ if (!validate_handle(socket_fd)) {
+ watch_item_destroy_all(socket_fd);
+ return FALSE;
+ }
+
+ /* Keep server running */
+ return TRUE;
}
EAPI int com_core_server_create(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data)
@@ -275,6 +387,23 @@ EAPI int com_core_server_create(const char *addr, int is_sync, int (*service_cb)
return -EIO;
}
+ if (watch_item_create(fd, fd, id, cbdata) < 0) {
+ GError *err = NULL;
+
+ ErrPrint("Failed to create a watch item\n");
+ g_source_remove(id);
+
+ free(cbdata);
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
+ }
+ g_io_channel_unref(gio);
+ secure_socket_destroy_handle(fd);
+ return -ENOMEM;
+ }
+
g_io_channel_unref(gio);
return fd;
}
@@ -336,7 +465,7 @@ EAPI int com_core_client_create(const char *addr, int is_sync, int (*service_cb)
g_io_channel_unref(gio);
- invoke_con_cb_list(client_fd);
+ invoke_con_cb_list(client_fd, client_fd, id, cbdata, 1);
return client_fd;
}
@@ -534,7 +663,7 @@ 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);
+ invoke_disconn_cb_list(handle, 1, 1, 1);
secure_socket_destroy_handle(handle);
return 0;
}
@@ -542,7 +671,7 @@ EAPI int com_core_server_destroy(int handle)
EAPI int com_core_client_destroy(int handle)
{
DbgPrint("Close client handle[%d]\n", handle);
- invoke_disconn_cb_list(handle);
+ invoke_disconn_cb_list(handle, 1, 1, 1);
secure_socket_destroy_handle(handle);
return 0;
}
diff --git a/src/com-core_thread.c b/src/com-core_thread.c
index eaa88b5..2a8fc5a 100644
--- a/src/com-core_thread.c
+++ b/src/com-core_thread.c
@@ -499,7 +499,7 @@ static gboolean evt_pipe_cb(GIOChannel *src, GIOCondition cond, gpointer data)
errout:
DbgPrint("Disconnecting\n");
- invoke_disconn_cb_list(tcb->handle);
+ invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
terminate_thread(tcb);
tcb_destroy(tcb);
return FALSE;
@@ -624,6 +624,7 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data)
}
g_io_channel_set_close_on_unref(gio, FALSE);
+
tcb->id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)evt_pipe_cb, tcb);
if (tcb->id == 0) {
GError *err = NULL;
@@ -641,12 +642,12 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data)
}
g_io_channel_unref(gio);
- invoke_con_cb_list(tcb->handle);
+ invoke_con_cb_list(tcb->handle, tcb->handle, 0, NULL, 0);
ret = pthread_create(&tcb->thid, NULL, client_cb, tcb);
if (ret != 0) {
ErrPrint("Thread creation failed: %s\n", strerror(ret));
- invoke_disconn_cb_list(tcb->handle);
+ invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
secure_socket_destroy_handle(tcb->handle);
tcb_destroy(tcb);
server_destroy(server);
@@ -717,12 +718,12 @@ EAPI int com_core_thread_client_create(const char *addr, int is_sync, int (*serv
g_io_channel_unref(gio);
- invoke_con_cb_list(tcb->handle);
+ invoke_con_cb_list(tcb->handle, tcb->handle, 0, NULL, 0);
ret = pthread_create(&tcb->thid, NULL, client_cb, tcb);
if (ret != 0) {
ErrPrint("Thread creation failed: %s\n", strerror(ret));
- invoke_disconn_cb_list(tcb->handle);
+ invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
secure_socket_destroy_handle(tcb->handle);
tcb_destroy(tcb);
return -EFAULT;
@@ -972,7 +973,7 @@ EAPI int com_core_thread_server_destroy(int handle)
continue;
}
- invoke_disconn_cb_list(handle);
+ invoke_disconn_cb_list(handle, 0, 0, 0);
terminate_thread(tcb);
tcb_destroy(tcb);
return 0;
@@ -983,7 +984,7 @@ EAPI int com_core_thread_server_destroy(int handle)
continue;
}
- invoke_disconn_cb_list(handle);
+ invoke_disconn_cb_list(handle, 0, 0, 0);
server_destroy(server);
return 0;
}
@@ -1004,7 +1005,7 @@ EAPI int com_core_thread_client_destroy(int handle)
return -ENOENT;
}
- invoke_disconn_cb_list(handle);
+ invoke_disconn_cb_list(handle, 0, 0, 0);
terminate_thread(tcb);
tcb_destroy(tcb);
return 0;