Handling the error case. for preventing the lock-up
authorSung-jae Park <nicesj.park@samsung.com>
Thu, 26 Jul 2012 03:03:02 +0000 (12:03 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Thu, 26 Jul 2012 06:46:19 +0000 (15:46 +0900)
Try to send/recv packet and check the time.
If it exceed the maximum waiting time,
Just stop and give up send/recv packet
And return false to handling it correctly by user.

Handling the exceptional case more hardly.

Decrease the timeout value to 2 secs from 10 secs

Change-Id: I4d78f471d1555c66b687e4979a7110b62325e7e6

debian/changelog
packaging/libcom-core.spec
src/com-core.c
src/com-core_packet.c
src/secure_socket.c

index 25f4572..a6879bb 100644 (file)
@@ -1,3 +1,10 @@
+com-core (0.1.0) unstable; urgency=low
+
+  * Git: slp/pkgs/c/com-core
+  * Tag: com-core_0.1.0
+
+ -- Sung-jae Park <nicesj.park@samsung.com>  Thu, 26 Jul 2012 14:15:08 +0900
+
 com-core (0.0.6) unstable; urgency=low
 
   * Git: slp/pkgs/c/com-core
index efb6695..61e5c2e 100644 (file)
@@ -1,6 +1,6 @@
 Name: libcom-core
 Summary: Library for the light-weight IPC 
-Version: 0.0.6
+Version: 0.1.0
 Release: 1
 Group: main/util
 License: Samsung Proprietary License
index 6e5f24a..0ce0c71 100644 (file)
@@ -79,6 +79,13 @@ static gboolean client_cb(GIOChannel *src, GIOCondition cond, gpointer data)
                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);
+               secure_socket_remove_connection_handle(client_fd);
+               return FALSE;
+       }
+
        if (ioctl(client_fd, FIONREAD, &readsize) < 0 || readsize == 0) {
                DbgPrint("Client is disconencted (readsize: %d)\n", readsize);
                invoke_disconn_cb_list(client_fd);
@@ -107,6 +114,16 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data)
        socket_fd = g_io_channel_unix_get_fd(src);
        if (!(cond & G_IO_IN)) {
                ErrPrint("Accept socket closed\n");
+               if (close(socket_fd) < 0)
+                       ErrPrint("Close error[%d]: %s\n", socket_fd, strerror(errno));
+               free(data);
+               return FALSE;
+       }
+
+       if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
+               DbgPrint("Client connection is lost\n");
+               if (close(socket_fd) < 0)
+                       ErrPrint("Close error[%d]: %s\n", socket_fd, strerror(errno));
                free(data);
                return FALSE;
        }
@@ -131,16 +148,18 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data)
                return FALSE;
        }
 
+       g_io_channel_set_close_on_unref(gio, FALSE);
+
        id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, client_cb, data);
        if (id < 0) {
                GError *err = NULL;
                ErrPrint("Failed to add IO watch\n");
-               g_io_channel_unref(gio);
                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_remove_connection_handle(client_fd);
                free(data);
                return FALSE;
@@ -187,22 +206,26 @@ EAPI int com_core_server_create(const char *addr, int is_sync, int (*service_cb)
        if (!gio) {
                ErrPrint("Failed to create new io channel\n");
                free(cbdata);
-               close(fd);
+               if (close(fd) < 0)
+                       ErrPrint("Close error[%d]: %s\n", fd, strerror(errno));
                return -EIO;
        }
 
+       g_io_channel_set_close_on_unref(gio, FALSE);
+
        id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc)accept_cb, cbdata);
        if (id < 0) {
                GError *err = NULL;
                ErrPrint("Failed to add IO watch\n");
                free(cbdata);
-               g_io_channel_unref(gio);
                g_io_channel_shutdown(gio, TRUE, &err);
                if (err) {
                        ErrPrint("Shutdown: %s\n", err->message);
                        g_error_free(err);
                }
-               close(fd);
+               g_io_channel_unref(gio);
+               if (close(fd) < 0)
+                       ErrPrint("Close error[%d]: %s\n", fd, strerror(errno));
                return -EIO;
        }
 
@@ -244,22 +267,26 @@ EAPI int com_core_client_create(const char *addr, int is_sync, int (*service_cb)
        if (!gio) {
                ErrPrint("Failed to create a new IO channel\n");
                free(cbdata);
-               close(client_fd);
+               if (close(client_fd) < 0)
+                       ErrPrint("Close error[%d]: %s\n", client_fd, strerror(errno));
                return -EIO;
        }
 
+       g_io_channel_set_close_on_unref(gio, FALSE);
+
        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");
                free(cbdata);
-               g_io_channel_unref(gio);
                g_io_channel_shutdown(gio, TRUE, &err);
                if (err) {
                        ErrPrint("Shutdown: %s\n", err->message);
                        g_error_free(err);
                }
-               close(client_fd);
+               g_io_channel_unref(gio);
+               if (close(client_fd) < 0)
+                       ErrPrint("Close error[%d]: %s\n", client_fd, strerror(errno));
                return -EIO;
        }
 
@@ -320,13 +347,15 @@ EAPI void *com_core_del_event_callback(enum com_core_event_type type, int (*cb)(
 
 EAPI int com_core_server_destroy(int handle)
 {
-       close(handle);
+       if (close(handle) < 0)
+               ErrPrint("Close error[%d]: %s\n", handle, strerror(errno));
        return 0;
 }
 
 EAPI int com_core_client_destroy(int handle)
 {
-       close(handle);
+       if (close(handle) < 0)
+               ErrPrint("Close error[%d]: %s\n", handle, strerror(errno));
        return 0;
 }
 
index 6135146..1c79f2b 100644 (file)
@@ -16,6 +16,8 @@
 #include "com-core_packet.h"
 #include "util.h"
 
+#define DEFAULT_TIMEOUT 2
+
 static struct info {
        struct dlist *recv_list;
        struct dlist *request_list;
@@ -398,11 +400,15 @@ EAPI int com_core_packet_send_only(int handle, struct packet *packet)
 EAPI struct packet *com_core_packet_oneshot_send(const char *addr, struct packet *packet)
 {
        int ret;
+       int sz;
        int fd;
        pid_t pid;
        int offset;
        struct packet *result = NULL;
        void *ptr;
+       struct timeval stv;
+       struct timeval etv;
+       struct timeval rtv;
 
        fd = secure_socket_create_client(addr);
        if (fd < 0)
@@ -411,41 +417,86 @@ EAPI struct packet *com_core_packet_oneshot_send(const char *addr, struct packet
        if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
                ErrPrint("fcntl: %s\n", strerror(errno));
 
-       ret = secure_socket_send(fd, (void *)packet_data(packet), packet_size(packet));
-       if (ret != packet_size(packet)) {
-               secure_socket_destroy(fd);
-               return NULL;
-       }
+       if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+               ErrPrint("Error: %s\n", strerror(errno));
+
+       gettimeofday(&stv, NULL);
+       sz = 0;
+       do {
+               ret = secure_socket_send(fd, (char *)packet_data(packet) + sz, packet_size(packet) - sz);
+               if (ret < 0) {
+                       secure_socket_destroy(fd);
+                       return NULL;
+               }
+
+               sz += ret;
+
+               gettimeofday(&etv, NULL);
+               timersub(&etv, &stv, &rtv);
+               if (rtv.tv_sec > DEFAULT_TIMEOUT) {
+                       ErrPrint("Timeout\n");
+                       secure_socket_destroy(fd);
+                       return NULL;
+               }
+       } while (sz < packet_size(packet));
 
        offset = 0;
        ptr = malloc(packet_header_size());
        if (!ptr) {
+               ErrPrint("Heap: %s\n", strerror(errno));
                secure_socket_destroy(fd);
                return NULL;
        }
 
-       ret = secure_socket_recv(fd, ptr, packet_header_size(), &pid);
-       if (ret < 0) {
-               free(ptr);
-               secure_socket_destroy(fd);
-               return NULL;
-       }
+       gettimeofday(&stv, NULL);
+       sz = 0;
+       do {
+               ret = secure_socket_recv(fd, (char *)ptr + sz, packet_header_size() - sz, &pid);
+               if (ret < 0) {
+                       free(ptr);
+                       secure_socket_destroy(fd);
+                       return NULL;
+               }
+               sz += ret;
+               gettimeofday(&etv, NULL);
+               timersub(&etv, &stv, &rtv);
+               if (rtv.tv_sec > DEFAULT_TIMEOUT) {
+                       ErrPrint("Timeout\n");
+                       free(ptr);
+                       secure_socket_destroy(fd);
+                       return NULL;
+               }
+       } while (sz < packet_header_size());
        result = packet_build(result, offset, ptr, ret);
        offset += ret;
        free(ptr);
 
        ptr = malloc(packet_payload_size(result));
        if (!ptr) {
+               ErrPrint("Heap: %s\n", strerror(errno));
                secure_socket_destroy(fd);
                return NULL;
        }
 
-       ret = secure_socket_recv(fd, ptr, packet_payload_size(result), &pid);
-       if (ret < 0) {
-               free(ptr);
-               secure_socket_destroy(fd);
-               return NULL;
-       }
+       gettimeofday(&stv, NULL);
+       sz = 0;
+       do {
+               ret = secure_socket_recv(fd, (char *)ptr + sz, packet_payload_size(result) - sz, &pid);
+               if (ret < 0) {
+                       free(ptr);
+                       secure_socket_destroy(fd);
+                       return NULL;
+               }
+               sz += ret;
+               gettimeofday(&etv, NULL);
+               timersub(&etv, &stv, &rtv);
+               if (rtv.tv_sec > DEFAULT_TIMEOUT) {
+                       ErrPrint("Timeout\n");
+                       free(ptr);
+                       secure_socket_destroy(fd);
+                       return NULL;
+               }
+       } while (sz < packet_payload_size(result));
        result = packet_build(result, offset, ptr, ret);
        offset += ret;
        free(ptr);
index 56c3dbb..e43b71e 100644 (file)
@@ -16,6 +16,8 @@
 #include "debug.h"
 #include "util.h"
 
+#define BACKLOG 50     /*!< Accept only 50 connections as default */
+
 int errno;
 
 static inline int create_socket(const char *peer, struct sockaddr_un *addr)
@@ -67,8 +69,12 @@ EAPI int secure_socket_create_client(const char *peer)
                return -1;
        }
 
-       if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0)
+       if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
                ErrPrint("Failed to change sock opt : %s\n", strerror(errno));
+               if (close(handle) < 0)
+                       ErrPrint("close a handle: %s\n", strerror(errno));
+               return -1;
+       }
 
        return handle;
 }
@@ -92,7 +98,7 @@ EAPI int secure_socket_create_server(const char *peer)
                return -1;
        }
 
-       state = listen(handle, 10); /* BACKLOG 10 */
+       state = listen(handle, BACKLOG);
        if (state < 0) {
                ErrPrint("Failed to listen a socket %s\n", strerror(errno));
 
@@ -122,8 +128,12 @@ EAPI int secure_socket_get_connection_handle(int server_handle)
                return -1;
        }
 
-       if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0)
+       if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
                ErrPrint("Failed to change sock opt : %s\n", strerror(errno));
+               if (close(handle) < 0)
+                       ErrPrint("Close a handle: %s\n", strerror(errno));
+               return -1;
+       }
 
        return handle;
 }
@@ -152,6 +162,10 @@ EAPI int secure_socket_send(int handle, const char *buffer, int size)
 
        ret = sendmsg(handle, &msg, 0);
        if (ret < 0) {
+               if (errno == EAGAIN || errno == EWOULDBLOCK) {
+                       ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
+                       return 0;
+               }
                ErrPrint("Failed to send message [%s]\n", strerror(errno));
                return -1;
        }
@@ -178,6 +192,11 @@ EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid)
        msg.msg_controllen = sizeof(control);
 
        if (recvmsg(handle, &msg, 0) < 0) {
+               if (errno == EAGAIN || errno == EWOULDBLOCK) {
+                       ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
+                       return 0;
+               }
+
                ErrPrint("Failed to recvmsg [%s]\n", strerror(errno));
                return -1;
        }
@@ -200,7 +219,7 @@ EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid)
 EAPI int secure_socket_destroy(int handle)
 {
        if (close(handle) < 0) {
-               ErrPrint("Failed to close a handle\n");
+               ErrPrint("Failed to close a handle: %s\n", strerror(errno));
                return -1;
        }
        return 0;