summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSung-jae Park <nicesj.park@samsung.com>2014-01-05 17:13:02 +0900
committerSung-jae Park <nicesj.park@samsung.com>2014-01-05 17:13:02 +0900
commitaf403278182b25e76be6b281a8145db6c615f2a7 (patch)
tree769492292c4877838c426bb3b355be4b4a3ae278
parentb63a3bb2deb3759d6987fffd40759bd4667776b4 (diff)
downloadcom-core-af403278182b25e76be6b281a8145db6c615f2a7.tar.gz
com-core-af403278182b25e76be6b281a8145db6c615f2a7.tar.bz2
com-core-af403278182b25e76be6b281a8145db6c615f2a7.zip
Sync with the latest product code of phone profile
Disable O_NONBLOCK option for creating a "pipe". It makes unpredictable busy waiting problem when it fails to write data to pipe. In some cases, the consumer thread could not empty the pipe, the producer thread failed to write with EAGAIN error if the pipe created with O_NONBLOCK. then the producer thread fall into the busy waiting status. This patch will keep the producer from busy waiting problem. Change-Id: I34d1433b4c380deb2bc8f03d476943652de6c23f
-rw-r--r--include/secure_socket.h6
-rw-r--r--packaging/libcom-core.spec2
-rw-r--r--src/com-core_thread.c61
-rw-r--r--src/secure_socket.c29
4 files changed, 84 insertions, 14 deletions
diff --git a/include/secure_socket.h b/include/secure_socket.h
index c5c7c35..ade51ab 100644
--- a/include/secure_socket.h
+++ b/include/secure_socket.h
@@ -29,6 +29,12 @@ extern "C" {
#define COM_CORE_LOCAL_SCHEME_LEN (8)
/*!
+ * sdlocal:///tmp/.socket.file => /tmp/.socket.file
+ */
+#define COM_CORE_SD_LOCAL_SCHEME "sdlocal://"
+#define COM_CORE_SD_LOCAL_SCHEME_LEN (10)
+
+/*!
* remote://IPADDR:PORT
* remote://:PORT => Using INADDR_ANY in this case
*/
diff --git a/packaging/libcom-core.spec b/packaging/libcom-core.spec
index 746eaac..804dc92 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.3
+Version: 0.5.6
Release: 1
Group: Base/IPC
License: Apache-2.0
diff --git a/src/com-core_thread.c b/src/com-core_thread.c
index c7b1eec..28ff288 100644
--- a/src/com-core_thread.c
+++ b/src/com-core_thread.c
@@ -87,6 +87,32 @@ struct tcb {
void *data;
};
+static ssize_t write_safe(int fd, const void *data, size_t bufsz)
+{
+ int ret;
+ int again;
+
+ do {
+ again = 0;
+ ret = write(fd, data, bufsz);
+ if (ret < 0) {
+ ret = -errno;
+ switch (ret) {
+ case -EAGAIN:
+ case -EINTR:
+ again = 1;
+ ErrPrint("Interrupted[%d] Again[%d]\n", fd, -ret);
+ break;
+ default:
+ ErrPrint("Failed to write: %s (%d)\n", strerror(-ret), -ret);
+ return ret;
+ }
+ }
+ } while (again);
+
+ return ret;
+}
+
/*!
* \NOTE
* Running thread: Main
@@ -150,8 +176,8 @@ static inline void terminate_thread(struct tcb *tcb)
void *res = NULL;
struct chunk *chunk;
- if (write(tcb->ctrl_pipe[PIPE_WRITE], &tcb, sizeof(tcb)) != sizeof(tcb)) {
- ErrPrint("Unable to write CTRL pipe\n");
+ if (write_safe(tcb->ctrl_pipe[PIPE_WRITE], &tcb, sizeof(tcb)) != sizeof(tcb)) {
+ ErrPrint("Unable to write CTRL pipe (%d)\n", sizeof(tcb));
}
secure_socket_destroy_handle(tcb->handle);
@@ -159,9 +185,9 @@ static inline void terminate_thread(struct tcb *tcb)
status = pthread_join(tcb->thid, &res);
if (status != 0) {
ErrPrint("Join: %s\n", strerror(status));
- }
- else
+ } else {
ErrPrint("Thread returns: %d\n", (int)res);
+ }
dlist_foreach_safe(tcb->chunk_list, l, n, chunk) {
/*!
@@ -200,7 +226,7 @@ static inline void chunk_remove(struct tcb *tcb, struct chunk *chunk)
* \NOTE
* Running thread: Other
*/
-static inline void chunk_append(struct tcb *tcb, struct chunk *chunk)
+static inline int chunk_append(struct tcb *tcb, struct chunk *chunk)
{
char event_ch = EVENT_READY;
int ret;
@@ -211,10 +237,14 @@ static inline void chunk_append(struct tcb *tcb, struct chunk *chunk)
CRITICAL_SECTION_END(&tcb->chunk_lock);
- ret = write(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch));
+ ret = write_safe(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch));
if (ret < 0) {
- ErrPrint("write: %s\n", strerror(errno));
- return;
+ CRITICAL_SECTION_BEGIN(&tcb->chunk_lock);
+
+ dlist_remove_data(tcb->chunk_list, chunk);
+
+ CRITICAL_SECTION_END(&tcb->chunk_lock);
+ return ret;
}
if (ret != sizeof(event_ch)) {
@@ -223,6 +253,7 @@ static inline void chunk_append(struct tcb *tcb, struct chunk *chunk)
/* Take a breathe */
pthread_yield();
+ return 0;
}
/*!
@@ -392,14 +423,18 @@ static void *client_cb(void *data)
/*!
* Count of chunk elements are same with PIPE'd data
*/
- chunk_append(tcb, chunk);
+ if (chunk_append(tcb, chunk) < 0) {
+ destroy_chunk(chunk);
+ break;
+ }
}
DbgPrint("Client CB is terminated (%d)\n", tcb->handle);
/* Wake up main thread to get disconnected event */
event_ch = EVENT_TERM;
- if (write(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
- ErrPrint("write: %s\n", strerror(errno));
+
+ if (write_safe(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
+ ErrPrint("%d byte is not written\n", sizeof(event_ch));
}
return (void *)(unsigned long)ret;
@@ -501,7 +536,7 @@ static inline struct tcb *tcb_create(int client_fd, int is_sync, int (*service_c
return NULL;
}
- if (pipe2(tcb->evt_pipe, (is_sync ? 0 : O_NONBLOCK) | O_CLOEXEC) < 0) {
+ if (pipe2(tcb->evt_pipe, O_CLOEXEC) < 0) {
ErrPrint("Error: %s\n", strerror(errno));
status = pthread_mutex_destroy(&tcb->chunk_lock);
if (status != 0) {
@@ -511,7 +546,7 @@ static inline struct tcb *tcb_create(int client_fd, int is_sync, int (*service_c
return NULL;
}
- if (pipe2(tcb->ctrl_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {
+ if (pipe2(tcb->ctrl_pipe, O_CLOEXEC) < 0) {
ErrPrint("Error: %s\n", strerror(errno));
CLOSE_PIPE(tcb->evt_pipe);
diff --git a/src/secure_socket.c b/src/secure_socket.c
index dd54924..58cc898 100644
--- a/src/secure_socket.c
+++ b/src/secure_socket.c
@@ -29,6 +29,7 @@
#include <netinet/tcp.h>
#include <errno.h>
#include <stdlib.h>
+#include <systemd/sd-daemon.h>
#include <dlog.h>
@@ -107,6 +108,23 @@ static inline int create_inet_socket(const char *peer, int port, struct sockaddr
return handle;
}
+static inline int create_systemd_socket(const char *peer, int port, struct sockaddr *addr)
+{
+ int handle = -1;
+ int cnt;
+
+ cnt = sd_listen_fds(0);
+ if (cnt > 1) {
+ ErrPrint("To many file descriptors are received on socket activation: %d\n", cnt);
+ } else if (cnt == 1) {
+ handle = SD_LISTEN_FDS_START + 0;
+ } else {
+ handle = create_inet_socket(peer, port, addr);
+ }
+
+ return handle;
+}
+
static inline int setup_unix_handle(int handle)
{
int on = 1;
@@ -157,6 +175,17 @@ static inline char *parse_scheme(const char *peer, int *port, struct function_ta
vtable->create_socket = create_unix_socket;
vtable->setup_handle = setup_unix_handle;
+ } else if (!strncasecmp(peer, COM_CORE_SD_LOCAL_SCHEME, COM_CORE_SD_LOCAL_SCHEME_LEN)) {
+ vtable->type = (int)SCHEME_LOCAL;
+ peer += COM_CORE_SD_LOCAL_SCHEME_LEN;
+
+ addr = strdup(peer);
+ if (!addr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ }
+
+ vtable->create_socket = create_systemd_socket;
+ vtable->setup_handle = setup_unix_handle;
} else if (!strncasecmp(peer, COM_CORE_REMOTE_SCHEME, COM_CORE_REMOTE_SCHEME_LEN)) {
register int len;
char *endptr;