diff options
author | Sung-jae Park <nicesj.park@samsung.com> | 2013-04-23 08:59:57 +0900 |
---|---|---|
committer | Sung-jae Park <nicesj.park@samsung.com> | 2013-04-23 08:59:57 +0900 |
commit | 5f77e1b8426962ceb6696fc78b06a2c5fad57537 (patch) | |
tree | 39439e992f0375ec2d4429031409c88fec45d28c | |
parent | cc50a4eccfce0ef96156f3b49b3d33f8d1fdbb0f (diff) | |
download | data-provider-master-5f77e1b8426962ceb6696fc78b06a2c5fad57537.tar.gz data-provider-master-5f77e1b8426962ceb6696fc78b06a2c5fad57537.tar.bz2 data-provider-master-5f77e1b8426962ceb6696fc78b06a2c5fad57537.zip |
Implement the service threads.
Shortcut service thread is enabled.
Service connection method is updated
(using vconf to notify running state of the master.)
Change-Id: I92af0e2e693c4516b407263bfb1fae9a8925f83e
-rwxr-xr-x | data/data-provider-master | 1 | ||||
-rw-r--r-- | include/conf.h | 4 | ||||
-rw-r--r-- | include/service_common.h | 5 | ||||
-rw-r--r-- | include/shortcut_service.h | 3 | ||||
-rw-r--r-- | include/util.h | 44 | ||||
-rw-r--r-- | packaging/data-provider-master.spec | 3 | ||||
-rw-r--r-- | src/event.c | 231 | ||||
-rw-r--r-- | src/main.c | 8 | ||||
-rw-r--r-- | src/service_common.c | 455 | ||||
-rw-r--r-- | src/setting.c | 5 | ||||
-rw-r--r-- | src/shortcut_service.c | 24 |
11 files changed, 429 insertions, 354 deletions
diff --git a/data/data-provider-master b/data/data-provider-master index a68b7d5..3c04aaf 100755 --- a/data/data-provider-master +++ b/data/data-provider-master @@ -23,6 +23,7 @@ launch_provider() # PROVIDER_DISABLE_CALL_OPTION=false # PROVIDER_METHOD="shm", "pixmap", "file" (default = "file") BUFMGR_LOCK_TYPE="once" BUFMGR_MAP_CACHE="true" /usr/bin/data-provider-master + vconftool set -t bool memory/data-provider-master/started 0 -f let RETRY_COUNT=$RETRY_COUNT+1 if [ $RETRY_COUNT -gt 5 ]; then echo "EXCEED THE MAXIMUM RETRY COUNT: $RETRY_COUNT (max 5)" diff --git a/include/conf.h b/include/conf.h index 87d1070..50a171b 100644 --- a/include/conf.h +++ b/include/conf.h @@ -155,6 +155,10 @@ extern int conf_loader(void); #define DEFAULT_CLUSTER "user,created" #define MINIMUM_REACTIVATION_TIME 10 +#if !defined(VCONFKEY_MASTER_STARTED) +#define VCONFKEY_MASTER_STARTED "memory/data-provider-master/started" +#endif + #define USE_XMONITOR g_conf.use_xmonitor #define HAPI __attribute__((visibility("hidden"))) diff --git a/include/service_common.h b/include/service_common.h index 6b0e4dd..fa0188c 100644 --- a/include/service_common.h +++ b/include/service_common.h @@ -14,9 +14,8 @@ * limitations under the License. */ enum tcb_type { - TCB_CLIENT_TYPE_UNDEFINED = 0x00, - TCB_CLIENT_TYPE_APP = 0x01, - TCB_CLIENT_TYPE_SERVICE = 0x02, + TCB_CLIENT_TYPE_APP = 0x00, + TCB_CLIENT_TYPE_SERVICE = 0x01, TCB_CLIENT_TYPE_UNKNOWN = 0xff, }; diff --git a/include/shortcut_service.h b/include/shortcut_service.h index a7a146d..65031a2 100644 --- a/include/shortcut_service.h +++ b/include/shortcut_service.h @@ -14,4 +14,7 @@ * limitations under the License. */ +extern int shortcut_service_init(void); +extern int shortcut_service_fini(void); + /* End of a file */ diff --git a/include/util.h b/include/util.h index a474c06..75e4715 100644 --- a/include/util.h +++ b/include/util.h @@ -34,4 +34,48 @@ extern double util_time_delay_for_compensation(double period); #define SCHEMA_PIXMAP "pixmap://" #define SCHEMA_SHM "shm://" +#define CRITICAL_SECTION_BEGIN(handle) \ +do { \ + int ret; \ + ret = pthread_mutex_lock(handle); \ + if (ret != 0) \ + ErrPrint("Failed to lock: %s\n", strerror(ret)); \ +} while (0) + +#define CRITICAL_SECTION_END(handle) \ +do { \ + int ret; \ + ret = pthread_mutex_unlock(handle); \ + if (ret != 0) \ + ErrPrint("Failed to unlock: %s\n", strerror(ret)); \ +} while (0) + +#define CANCEL_SECTION_BEGIN() do { \ + int ret; \ + ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); \ + if (ret != 0) \ + ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \ +} while (0) + +#define CANCEL_SECTION_END() do { \ + int ret; \ + ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); \ + if (ret != 0) \ + ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \ +} while (0) + +#define CLOSE_PIPE(p) do { \ + int status; \ + status = close(p[PIPE_READ]); \ + if (status < 0) \ + ErrPrint("close: %s\n", strerror(errno)); \ + status = close(p[PIPE_WRITE]); \ + if (status < 0) \ + ErrPrint("close: %s\n", strerror(errno)); \ +} while (0) + +#define PIPE_READ 0 +#define PIPE_WRITE 1 +#define PIPE_MAX 2 + /* End of a file */ diff --git a/packaging/data-provider-master.spec b/packaging/data-provider-master.spec index c459cfe..ed82bd9 100644 --- a/packaging/data-provider-master.spec +++ b/packaging/data-provider-master.spec @@ -1,6 +1,6 @@ Name: data-provider-master Summary: Master service provider for liveboxes. -Version: 0.21.4 +Version: 0.22.0 Release: 1 Group: HomeTF/Livebox License: Flora License @@ -80,6 +80,7 @@ chown 0:5000 /opt/dbspace/.livebox.db chmod 640 /opt/dbspace/.livebox.db chown 0:5000 /opt/dbspace/.livebox.db-journal chmod 640 /opt/dbspace/.livebox.db-journal +vconftool set -t bool "memory/data-provider-master/started" 0 -i -u 5000 -f echo "Successfully installed. Please start a daemon again manually" echo "%{_sysconfdir}/init.d/data-provider-master start" diff --git a/src/event.c b/src/event.c index 818e66f..89c4e34 100644 --- a/src/event.c +++ b/src/event.c @@ -36,38 +36,6 @@ #include "conf.h" #include "event.h" -#define CRITICAL_SECTION_BEGIN(lock) do { \ - int ret; \ - ret = pthread_mutex_lock(&lock); \ - if (ret != 0) { \ - ErrPrint("Unable to get lock: %s\n", strerror(ret)); \ - } \ -} while (0) - -#define CRITICAL_SECTION_END(lock) do { \ - int ret; \ - ret = pthread_mutex_unlock(&lock); \ - if (ret != 0) { \ - ErrPrint("Unable to unlock: %s\n", strerror(ret)); \ - } \ -} while (0) - -#define CANCEL_SECTION_BEGIN() do { \ - int ret; \ - ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); \ - if (ret != 0) \ - ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \ -} while (0) - -#define CANCEL_SECTION_END() do { \ - int ret; \ - ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); \ - if (ret != 0) \ - ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \ -} while (0) - -#define PIPE_READ 0 -#define PIPE_WRITE 1 #define EVENT_CH 'e' int errno; @@ -77,8 +45,10 @@ static struct info { Eina_List *event_list; int handle; pthread_mutex_t event_list_lock; - int evt_pipe[2]; + int evt_pipe[PIPE_MAX]; + int tcb_pipe[PIPE_MAX]; Ecore_Fd_Handler *event_handler; + Ecore_Fd_Handler *tcb_handler; int (*event_cb)(enum event_state state, struct event_data *event, void *data); void *cbdata; @@ -144,9 +114,9 @@ static inline int processing_input_event(struct input_event *event) memcpy(item, &s_info.event_data, sizeof(*item)); - CRITICAL_SECTION_BEGIN(s_info.event_list_lock); + CRITICAL_SECTION_BEGIN(&s_info.event_list_lock); s_info.event_list = eina_list_append(s_info.event_list, item); - CRITICAL_SECTION_END(s_info.event_list_lock); + CRITICAL_SECTION_END(&s_info.event_list_lock); event_ch = EVENT_CH; if (write(s_info.evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) { @@ -225,7 +195,7 @@ static inline int processing_input_event(struct input_event *event) return LB_STATUS_SUCCESS; } -static void *event_main(void *data) +static void *event_thread_main(void *data) { fd_set set; int ret = 0; @@ -233,11 +203,11 @@ static void *event_main(void *data) char *ptr = (char *)&input_event; int offset = 0; int readsize = 0; + char event_ch = EVENT_CH; - DbgPrint("event_main initiated\n"); + DbgPrint("Initiated\n"); while (1) { - CANCEL_SECTION_BEGIN(); FD_ZERO(&set); FD_SET(s_info.handle, &set); ret = select(s_info.handle + 1, &set, NULL, NULL, NULL); @@ -245,18 +215,15 @@ static void *event_main(void *data) ret = -errno; if (errno == EINTR) { DbgPrint("Select receives INTR\n"); - CANCEL_SECTION_END(); continue; } ErrPrint("Error: %s\n", strerror(errno)); - CANCEL_SECTION_END(); - return (void *)ret; + break; } else if (ret == 0) { ErrPrint("Timeout expired\n"); - CANCEL_SECTION_END(); - return (void *)LB_STATUS_ERROR_TIMEOUT; + ret = LB_STATUS_ERROR_TIMEOUT; + break; } - CANCEL_SECTION_END(); if (!FD_ISSET(s_info.handle, &set)) { ErrPrint("Unexpected handle is toggled\n"); @@ -281,9 +248,84 @@ static void *event_main(void *data) } } + if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) + ErrPrint("Unable to write PIPE: %s\n", strerror(errno)); + return (void *)ret; } +static inline int reclaim_tcb_resources(void) +{ + int status; + struct event_data *event; + void *ret; + + if (close(s_info.handle) < 0) + ErrPrint("Unable to release the fd: %s\n", strerror(errno)); + + s_info.handle = -1; + DbgPrint("Event handler deactivated\n"); + + status = pthread_join(s_info.tid, &ret); + if (status != 0) + ErrPrint("Failed to join a thread: %s\n", strerror(errno)); + else + DbgPrint("Thread returns: %d\n", (int)ret); + + ecore_main_fd_handler_del(s_info.event_handler); + s_info.event_handler = NULL; + + ecore_main_fd_handler_del(s_info.tcb_handler); + s_info.tcb_handler = NULL; + + CLOSE_PIPE(s_info.tcb_pipe); + CLOSE_PIPE(s_info.evt_pipe); + + EINA_LIST_FREE(s_info.event_list, event) { + if (s_info.event_cb) { + if (s_info.event_state == EVENT_STATE_DEACTIVATE) { + s_info.event_state = EVENT_STATE_ACTIVATE; + } else if (s_info.event_state == EVENT_STATE_ACTIVATE) { + s_info.event_state = EVENT_STATE_ACTIVATED; + } + s_info.event_cb(s_info.event_state, event, s_info.cbdata); + } + free(event); + } + + if (s_info.event_state != EVENT_STATE_DEACTIVATE) { + s_info.event_state = EVENT_STATE_DEACTIVATE; + + if (s_info.event_cb) + s_info.event_cb(s_info.event_state, &s_info.event_data, s_info.cbdata); + } + + s_info.event_data.x = -1; + s_info.event_data.y = -1; + return LB_STATUS_SUCCESS; +} + +static Eina_Bool event_deactivate_cb(void *data, Ecore_Fd_Handler *handler) +{ + int fd; + char event_ch; + + fd = ecore_main_fd_handler_fd_get(handler); + if (fd < 0) { + ErrPrint("Invalid fd\n"); + return ECORE_CALLBACK_CANCEL; + } + + if (read(fd, &event_ch, sizeof(event_ch)) != sizeof(event_ch)) { + ErrPrint("Unable to read event ch: %s\n", strerror(errno)); + return ECORE_CALLBACK_CANCEL; + } + + DbgPrint("Deactivated event received: %c\n", event_ch); + reclaim_tcb_resources(); + return ECORE_CALLBACK_CANCEL; +} + static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler) { int fd; @@ -301,13 +343,13 @@ static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler) return ECORE_CALLBACK_CANCEL; } - CRITICAL_SECTION_BEGIN(s_info.event_list_lock); + CRITICAL_SECTION_BEGIN(&s_info.event_list_lock); item = eina_list_nth(s_info.event_list, 0); if (item) s_info.event_list = eina_list_remove(s_info.event_list, item); else ErrPrint("Unable to get event\n"); - CRITICAL_SECTION_END(s_info.event_list_lock); + CRITICAL_SECTION_END(&s_info.event_list_lock); if (item && s_info.event_cb) { switch (s_info.event_state) { @@ -328,6 +370,9 @@ static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler) return ECORE_CALLBACK_RENEW; } +/*! + * x, y is the starting point. + */ HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data) { int status; @@ -358,37 +403,56 @@ HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, st return LB_STATUS_ERROR_FAULT; } + status = pipe2(s_info.tcb_pipe, O_NONBLOCK | O_CLOEXEC); + if (status < 0) { + ErrPrint("Unable to prepare tcb pipe: %s\n", strerror(errno)); + if (close(s_info.handle) < 0) + ErrPrint("Failed to close handle: %s\n", strerror(errno)); + s_info.handle = -1; + CLOSE_PIPE(s_info.evt_pipe); + return LB_STATUS_ERROR_FAULT; + } + s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL); if (!s_info.event_handler) { if (close(s_info.handle) < 0) ErrPrint("Failed to close handle: %s\n", strerror(errno)); + s_info.handle = -1; - if (close(s_info.evt_pipe[PIPE_READ]) < 0) - ErrPrint("Failed to close handle: %s\n", strerror(errno)); + CLOSE_PIPE(s_info.tcb_pipe); + CLOSE_PIPE(s_info.evt_pipe); + return LB_STATUS_ERROR_FAULT; + } - if (close(s_info.evt_pipe[PIPE_WRITE]) < 0) - ErrPrint("Failed to close handle: %s\n", strerror(errno)); + s_info.tcb_handler = ecore_main_fd_handler_add(s_info.tcb_pipe[PIPE_READ], ECORE_FD_READ, event_deactivate_cb, NULL, NULL, NULL); + if (!s_info.event_handler) { + ecore_main_fd_handler_del(s_info.event_handler); + s_info.event_handler = NULL; + if (close(s_info.handle) < 0) + ErrPrint("Failed to close handle: %s\n", strerror(errno)); s_info.handle = -1; + + CLOSE_PIPE(s_info.tcb_pipe); + CLOSE_PIPE(s_info.evt_pipe); return LB_STATUS_ERROR_FAULT; } - status = pthread_create(&s_info.tid, NULL, event_main, NULL); + status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL); if (status != 0) { ErrPrint("Failed to initiate the thread: %s\n", strerror(status)); ecore_main_fd_handler_del(s_info.event_handler); s_info.event_handler = NULL; + ecore_main_fd_handler_del(s_info.tcb_handler); + s_info.tcb_handler = NULL; + if (close(s_info.handle) < 0) ErrPrint("close: %s\n", strerror(errno)); s_info.handle = -1; - if (close(s_info.evt_pipe[PIPE_READ]) < 0) - ErrPrint("close: %s\n", strerror(errno)); - - if (close(s_info.evt_pipe[PIPE_WRITE]) < 0) - ErrPrint("close: %s\n", strerror(errno)); - + CLOSE_PIPE(s_info.tcb_pipe); + CLOSE_PIPE(s_info.evt_pipe); return LB_STATUS_ERROR_FAULT; } @@ -403,63 +467,12 @@ HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, st HAPI int event_deactivate(void) { - int status; - struct event_data *event; - void *ret; - if (s_info.handle < 0) { ErrPrint("Event handler is not actiavated\n"); return LB_STATUS_SUCCESS; } - status = pthread_cancel(s_info.tid); - if (status != 0) - ErrPrint("Failed to cacnel a thread: %s\n", strerror(errno)); - - status = pthread_join(s_info.tid, &ret); - if (status != 0) - ErrPrint("Failed to join a thread: %s\n", strerror(errno)); - else if (ret == PTHREAD_CANCELED) - DbgPrint("Thread is canceled\n"); - - ecore_main_fd_handler_del(s_info.event_handler); - s_info.event_handler = NULL; - - if (close(s_info.evt_pipe[PIPE_READ]) < 0) - ErrPrint("Failed to close: %s\n", strerror(errno)); - - if (close(s_info.evt_pipe[PIPE_WRITE]) < 0) - ErrPrint("Failed to close: %s\n", strerror(errno)); - - if (close(s_info.handle) < 0) - ErrPrint("Unable to release the fd: %s\n", strerror(errno)); - - s_info.handle = -1; - DbgPrint("Event handler deactivated\n"); - - EINA_LIST_FREE(s_info.event_list, event) { - if (s_info.event_cb) { - if (s_info.event_state == EVENT_STATE_DEACTIVATE) { - s_info.event_state = EVENT_STATE_ACTIVATE; - } else if (s_info.event_state == EVENT_STATE_ACTIVATE) { - s_info.event_state = EVENT_STATE_ACTIVATED; - } - s_info.event_cb(s_info.event_state, event, s_info.cbdata); - } - free(event); - } - - if (s_info.event_state != EVENT_STATE_DEACTIVATE) { - s_info.event_state = EVENT_STATE_DEACTIVATE; - - if (s_info.event_cb) - s_info.event_cb(s_info.event_state, &s_info.event_data, s_info.cbdata); - } - - s_info.event_data.x = -1; - s_info.event_data.y = -1; - - return LB_STATUS_SUCCESS; + return reclaim_tcb_resources(); } HAPI int event_is_activated(void) @@ -28,6 +28,7 @@ #include <glib.h> #include <glib-object.h> #include <aul.h> +#include <vconf.h> #include <packet.h> #include <dlog.h> @@ -50,6 +51,7 @@ #include "debug.h" #include "critical_log.h" #include "event.h" +#include "shortcut_service.h" #if defined(FLOG) FILE *__file_log_fp; @@ -238,13 +240,19 @@ int main(int argc, char *argv[]) (void)util_unlink_files(IMAGE_PATH); (void)util_unlink_files(SLAVE_LOG_PATH); + shortcut_service_init(); script_init(); app_create(); + + vconf_set_bool(VCONFKEY_MASTER_STARTED, 1); ecore_main_loop_begin(); + vconf_set_bool(VCONFKEY_MASTER_STARTED, 0); + app_terminate(); script_fini(); + shortcut_service_fini(); ecore_evas_shutdown(); evas_shutdown(); diff --git a/src/service_common.c b/src/service_common.c index 15b5cb2..fd2a577 100644 --- a/src/service_common.c +++ b/src/service_common.c @@ -32,48 +32,26 @@ #include "debug.h" #include "conf.h" -#define EVT_CH 'e' +#define EVT_CH 'e' #define EVT_END_CH 'x' -#define CRITICAL_SECTION_BEGIN(handle) \ -do { \ - int ret; \ - ret = pthread_mutex_lock(handle); \ - if (ret != 0) \ - ErrPrint("Failed to lock: %s\n", strerror(ret)); \ -} while (0) - -#define CRITICAL_SECTION_END(handle) \ -do { \ - int ret; \ - ret = pthread_mutex_unlock(handle); \ - if (ret != 0) \ - ErrPrint("Failed to unlock: %s\n", strerror(ret)); \ -} while (0) - - int errno; /*! * \note * Server information and global (only in this file-scope) variables are defined */ -#define EVT_READ 0 -#define EVT_WRITE 1 -#define EVT_MAX 2 struct service_context { - pthread_t thid; /*!< Server thread Id */ + pthread_t server_thid; /*!< Server thread Id */ int fd; /*!< Server socket handle */ - pthread_t service_thid; - Eina_List *tcb_list; /*!< TCB list, list of every thread for client connections */ - pthread_mutex_t tcb_list_lock; /*!< tcb_list has to be handled safely */ Eina_List *packet_list; pthread_mutex_t packet_list_lock; - int evt_pipe[EVT_MAX]; + int evt_pipe[PIPE_MAX]; + int tcb_pipe[PIPE_MAX]; int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data); void *service_thread_data; @@ -98,38 +76,9 @@ struct tcb { /* Thread controll block */ }; /*! - * \note - * Called from Client Thread - */ -static inline int tcb_destroy(struct service_context *svc_ctx, struct tcb *tcb) -{ - void *ret; - int status; - - CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock); - svc_ctx->tcb_list = eina_list_remove(svc_ctx->tcb_list, tcb); - CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock); - - /*! - * ASSERT(tcb->fd >= 0); - */ - secure_socket_destroy_handle(tcb->fd); - - status = pthread_join(tcb->thid, &ret); - if (status != 0) - ErrPrint("Unable to join a thread: %s\n", strerror(status)); - /*! - * \NOTE - * Waiting termination client thread - */ - free(tcb); - - return 0; -} - -/*! - * Do service for clients + * Do services for clients * Routing packets to destination processes. + * CLIENT THREAD */ static void *client_packet_pump_main(void *data) { @@ -151,9 +100,11 @@ static void *client_packet_pump_main(void *data) RECV_DONE, } recv_state; struct packet_info *packet_info; + Eina_List *l; ret = 0; recv_state = RECV_INIT; + DbgPrint("Socket data pumping thread is activated\n"); /*! * \note * To escape from the switch statement, we use this ret value @@ -177,7 +128,7 @@ static void *client_packet_pump_main(void *data) break; } - if (FD_ISSET(tcb->fd, &set)) { + if (!FD_ISSET(tcb->fd, &set)) { ErrPrint("Unexpected handler is toggled\n"); ret = -EINVAL; break; @@ -223,9 +174,15 @@ static void *client_packet_pump_main(void *data) packet_offset += recv_offset; + size = packet_payload_size(packet); + if (size == 0) { + recv_state = RECV_DONE; + recv_offset = 0; + break; + } + recv_state = RECV_PAYLOAD; recv_offset = 0; - size = packet_payload_size(packet); ptr = malloc(size); if (!ptr) { @@ -261,6 +218,12 @@ static void *client_packet_pump_main(void *data) } break; case RECV_DONE: + default: + /* Dead code */ + break; + } + + if (recv_state == RECV_DONE) { /*! * Push this packet to the packet list with TCB * Then the service main function will get this. @@ -276,38 +239,52 @@ static void *client_packet_pump_main(void *data) packet_info->packet = packet; packet_info->tcb = tcb; + DbgPrint("New packet is built\n"); CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock); svc_ctx->packet_list = eina_list_append(svc_ctx->packet_list, packet_info); CRITICAL_SECTION_END(&svc_ctx->packet_list_lock); - if (write(svc_ctx->evt_pipe[EVT_WRITE], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) { + if (write(svc_ctx->evt_pipe[PIPE_WRITE], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) { ret = -errno; - ErrPrint("Unable to write a pipe\n"); + ErrPrint("Unable to write a pipe: %s\n", strerror(errno)); CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock); svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info); CRITICAL_SECTION_END(&svc_ctx->packet_list_lock); packet_destroy(packet); free(packet_info); + ErrPrint("Terminate thread: %p\n", tcb); break; + } else { + DbgPrint("Packet received: %d bytes\n", packet_offset); + recv_state = RECV_INIT; } - DbgPrint("Packet received: %d bytes\n", packet_offset); + } + } - recv_state = RECV_INIT; - break; - default: - /* Dead code */ - break; + CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock); + EINA_LIST_FOREACH(svc_ctx->packet_list, l, packet_info) { + if (packet_info->tcb == tcb) { + DbgPrint("Reset ptr of the TCB[%p] in the list of packet info\n", tcb); + packet_info->tcb = NULL; } } + CRITICAL_SECTION_END(&svc_ctx->packet_list_lock); + + /*! + * \note + * Emit a signal to collect this TCB from the SERVER THREAD. + */ + DbgPrint("Emit a signal to destroy TCB[%p]\n", tcb); + if (write(svc_ctx->tcb_pipe[PIPE_WRITE], &tcb, sizeof(tcb)) != sizeof(tcb)) + ErrPrint("Unable to write pipe: %s\n", strerror(errno)); - tcb_destroy(svc_ctx, tcb); return (void *)ret; } /*! * \note - * Called from Server Main Thread + * SERVER THREAD */ static inline struct tcb *tcb_create(struct service_context *svc_ctx, int fd) { @@ -322,7 +299,9 @@ static inline struct tcb *tcb_create(struct service_context *svc_ctx, int fd) tcb->fd = fd; tcb->svc_ctx = svc_ctx; + tcb->type = TCB_CLIENT_TYPE_APP; + DbgPrint("Create a new service thread [%d]\n", fd); status = pthread_create(&tcb->thid, NULL, client_packet_pump_main, tcb); if (status != 0) { ErrPrint("Unable to create a new thread: %s\n", strerror(status)); @@ -330,16 +309,13 @@ static inline struct tcb *tcb_create(struct service_context *svc_ctx, int fd) return NULL; } - CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock); svc_ctx->tcb_list = eina_list_append(svc_ctx->tcb_list, tcb); - CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock); - return tcb; } /*! * \note - * Called from Main Thread + * SERVER THREAD */ static inline void tcb_teminate_all(struct service_context *svc_ctx) { @@ -352,7 +328,6 @@ static inline void tcb_teminate_all(struct service_context *svc_ctx) * If we call this after terminate the server thread first. * Then there is no other thread to access tcb_list. */ - CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock); EINA_LIST_FREE(svc_ctx->tcb_list, tcb) { /*! * ASSERT(tcb->fd >= 0); @@ -362,79 +337,44 @@ static inline void tcb_teminate_all(struct service_context *svc_ctx) status = pthread_join(tcb->thid, &ret); if (status != 0) ErrPrint("Unable to join a thread: %s\n", strerror(status)); + else + DbgPrint("Thread returns: %d\n", (int)ret); free(tcb); } - CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock); } /*! - * \NOTE - * Packet consuming thread. service thread. + * \note + * SERVER THREAD */ -static void *service_main(void *data) +static inline void tcb_destroy(struct service_context *svc_ctx, struct tcb *tcb) { - struct service_context *svc_ctx = data; - fd_set set; - int ret; - char evt_ch; - struct packet_info *packet_info; - - while (1) { - FD_ZERO(&set); - FD_SET(svc_ctx->evt_pipe[EVT_READ], &set); - ret = select(svc_ctx->evt_pipe[EVT_READ] + 1, &set, NULL, NULL, NULL); - if (ret < 0) { - ret = -errno; - if (errno == EINTR) { - DbgPrint("INTERRUPTED\n"); - continue; - } - ErrPrint("Error: %s\n",strerror(errno)); - break; - } else if (ret == 0) { - ErrPrint("Timeout\n"); - ret = -ETIMEDOUT; - break; - } - - if (FD_ISSET(svc_ctx->evt_pipe[EVT_READ], &set)) { - ErrPrint("Unexpected handler is toggled\n"); - ret = -EINVAL; - break; - } - - if (read(svc_ctx->evt_pipe[EVT_READ], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) { - ErrPrint("Unable to read pipe: %s\n", strerror(errno)); - ret = -EIO; - break; - } - - if (evt_ch == EVT_END_CH) { - ErrPrint("Thread is terminated\n"); - ret = 0; - break; - } - - CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock); - packet_info = eina_list_nth(svc_ctx->packet_list, 0); - svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info); - CRITICAL_SECTION_END(&svc_ctx->packet_list_lock); + void *ret; + int status; - ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data); - if (ret < 0) - ErrPrint("Service thread returns: %d\n", ret); + svc_ctx->tcb_list = eina_list_remove(svc_ctx->tcb_list, tcb); + /*! + * ASSERT(tcb->fd >= 0); + * Close the connection, and then collecting the return value of thread + */ + secure_socket_destroy_handle(tcb->fd); - packet_destroy(packet_info->packet); - free(packet_info); - } + status = pthread_join(tcb->thid, &ret); + if (status != 0) + ErrPrint("Unable to join a thread: %s\n", strerror(status)); + else + DbgPrint("Thread returns: %d\n", (int)ret); - return (void *)ret; + free(tcb); } /*! * Accept new client connections * And create a new thread for service. + * + * Create Client threads & Destroying them + * SERVER THREAD */ static void *server_main(void *data) { @@ -443,11 +383,24 @@ static void *server_main(void *data) int ret; int client_fd; struct tcb *tcb; + int fd; + char evt_ch; + Eina_List *l; + Eina_List *n; + struct packet_info *packet_info; + + DbgPrint("Server thread is activated\n"); + fd = svc_ctx->fd > svc_ctx->tcb_pipe[PIPE_READ] ? svc_ctx->fd : svc_ctx->tcb_pipe[PIPE_READ]; + fd = fd > svc_ctx->evt_pipe[PIPE_READ] ? fd : svc_ctx->evt_pipe[PIPE_READ]; + fd += 1; while (1) { FD_ZERO(&set); FD_SET(svc_ctx->fd, &set); - ret = select(svc_ctx->fd + 1, &set, NULL, NULL, NULL); + FD_SET(svc_ctx->tcb_pipe[PIPE_READ], &set); + FD_SET(svc_ctx->evt_pipe[PIPE_READ], &set); + + ret = select(fd, &set, NULL, NULL, NULL); if (ret < 0) { ret = -errno; if (errno == EINTR) { @@ -463,27 +416,97 @@ static void *server_main(void *data) } if (FD_ISSET(svc_ctx->fd, &set)) { - ErrPrint("Unexpected handler is toggled\n"); - ret = -EINVAL; - break; - } + client_fd = secure_socket_get_connection_handle(svc_ctx->fd); + DbgPrint("New client connection arrived (%d)\n", client_fd); + if (client_fd < 0) { + ErrPrint("Failed to establish the client connection\n"); + ret = -EFAULT; + break; + } - client_fd = secure_socket_get_connection_handle(svc_ctx->fd); - DbgPrint("New client connection arrived (%d)\n", client_fd); - if (client_fd < 0) { - ErrPrint("Failed to establish the client connection\n"); - ret = -EFAULT; - break; + tcb = tcb_create(svc_ctx, client_fd); + if (!tcb) + secure_socket_destroy_handle(client_fd); + else + DbgPrint("Creating TCB[%p]\n", tcb); + } + + if (FD_ISSET(svc_ctx->tcb_pipe[PIPE_READ], &set)) { + if (read(svc_ctx->tcb_pipe[PIPE_READ], &tcb, sizeof(tcb)) != sizeof(tcb)) { + ErrPrint("Unable to read pipe: %s\n", strerror(errno)); + ret = -EFAULT; + break; + } + + DbgPrint("Destroying TCB[%p]\n", tcb); + /*! + * at this time, the client thread can access this tcb. + * how can I protect this TCB from deletion without disturbing the server thread? + */ + tcb_destroy(svc_ctx, tcb); + } + + if (FD_ISSET(svc_ctx->evt_pipe[PIPE_READ], &set)) { + if (read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) { + ErrPrint("Unable to read pipe: %s\n", strerror(errno)); + ret = -EFAULT; + break; + } + + DbgPrint("Event CH: %c\n", evt_ch); + + CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock); + packet_info = eina_list_nth(svc_ctx->packet_list, 0); + svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info); + CRITICAL_SECTION_END(&svc_ctx->packet_list_lock); + + /*! + * \CRITICAL + * What happens if the client thread is terminated, so the packet_info->tcb is deleted + * while processing svc_ctx->service_thread_main? + */ + ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data); + if (ret < 0) + ErrPrint("Service thread returns: %d\n", ret); + + packet_destroy(packet_info->packet); + free(packet_info); } - tcb = tcb_create(svc_ctx, client_fd); - if (!tcb) - secure_socket_destroy_handle(client_fd); + /* If there is no such triggered FD? */ + } + + /*! + * Consuming all pended packets before terminates server thread. + * + * If the server thread is terminated, we should flush all pended packets. + * And we should services them. + * While processing this routine, the mutex is locked. + * So every other client thread will be slowed down, sequently, every clients can meet problems. + * But in case of termination of server thread, there could be systemetic problem. + * This only should be happenes while terminating the master daemon process. + */ + CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock); + EINA_LIST_FOREACH_SAFE(svc_ctx->packet_list, l, n, packet_info) { + ret = read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch)); + DbgPrint("Flushing pipe: %d (%c)\n", ret, evt_ch); + svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info); + ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data); + if (ret < 0) + ErrPrint("Service thread returns: %d\n", ret); + packet_destroy(packet_info->packet); + free(packet_info); } + CRITICAL_SECTION_END(&svc_ctx->packet_list_lock); + tcb_teminate_all(svc_ctx); return (void *)ret; } +/*! + * \NOTE + * MAIN THREAD + */ HAPI struct service_context *service_common_create(const char *addr, int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data), void *data) { int status; @@ -494,7 +517,10 @@ HAPI struct service_context *service_common_create(const char *addr, int (*servi return NULL; } - svc_ctx = malloc(sizeof(*svc_ctx)); + if (unlink(addr) < 0) + ErrPrint("[%s] - %s\n", addr, strerror(errno)); + + svc_ctx = calloc(1, sizeof(*svc_ctx)); if (!svc_ctx) { ErrPrint("Heap: %s\n", strerror(errno)); return NULL; @@ -522,80 +548,33 @@ HAPI struct service_context *service_common_create(const char *addr, int (*servi return NULL; } - status = pthread_mutex_init(&svc_ctx->packet_list_lock, NULL); - if (status != 0) { - ErrPrint("Unable to create a mutex: %s\n", strerror(status)); - status = close(svc_ctx->evt_pipe[EVT_READ]); - if (status < 0) - ErrPrint("Error: %s\n", strerror(errno)); - status = close(svc_ctx->evt_pipe[EVT_WRITE]); - if (status < 0) - ErrPrint("Error: %s\n", strerror(errno)); - secure_socket_destroy_handle(svc_ctx->fd); - free(svc_ctx); - return NULL; - } - - status = pthread_mutex_init(&svc_ctx->tcb_list_lock, NULL); - if (status != 0) { - ErrPrint("Unable to initiate the mutex: %s\n", strerror(status)); - status = pthread_mutex_destroy(&svc_ctx->packet_list_lock); - if (status != 0) - ErrPrint("Error: %s\n", strerror(status)); - status = close(svc_ctx->evt_pipe[EVT_READ]); - if (status < 0) - ErrPrint("Error: %s\n", strerror(errno)); - status = close(svc_ctx->evt_pipe[EVT_WRITE]); - if (status < 0) - ErrPrint("Error: %s\n", strerror(errno)); + if (pipe2(svc_ctx->tcb_pipe, O_NONBLOCK | O_CLOEXEC) < 0) { + ErrPrint("pipe: %s\n", strerror(errno)); + CLOSE_PIPE(svc_ctx->evt_pipe); secure_socket_destroy_handle(svc_ctx->fd); free(svc_ctx); return NULL; } - status = pthread_create(&svc_ctx->thid, NULL, server_main, svc_ctx); + status = pthread_mutex_init(&svc_ctx->packet_list_lock, NULL); if (status != 0) { - ErrPrint("Unable to create a thread for shortcut service: %s\n", strerror(status)); - status = pthread_mutex_destroy(&svc_ctx->tcb_list_lock); - if (status != 0) - ErrPrint("Error: %s\n", strerror(status)); - status = pthread_mutex_destroy(&svc_ctx->packet_list_lock); - if (status != 0) - ErrPrint("Error: %s\n", strerror(status)); - status = close(svc_ctx->evt_pipe[EVT_READ]); - if (status != 0) - ErrPrint("Error: %s\n", strerror(status)); - status = close(svc_ctx->evt_pipe[EVT_WRITE]); - if (status != 0) - ErrPrint("Error: %s\n", strerror(status)); + ErrPrint("Unable to create a mutex: %s\n", strerror(status)); + CLOSE_PIPE(svc_ctx->evt_pipe); + CLOSE_PIPE(svc_ctx->tcb_pipe); secure_socket_destroy_handle(svc_ctx->fd); free(svc_ctx); return NULL; } - status = pthread_create(&svc_ctx->service_thid, NULL, service_main, svc_ctx); + DbgPrint("Creating server thread\n"); + status = pthread_create(&svc_ctx->server_thid, NULL, server_main, svc_ctx); if (status != 0) { - void *ret; ErrPrint("Unable to create a thread for shortcut service: %s\n", strerror(status)); - - secure_socket_destroy_handle(svc_ctx->fd); - - status = pthread_join(svc_ctx->thid, &ret); - if (status != 0) - ErrPrint("Error: %s\n", strerror(status)); - - status = pthread_mutex_destroy(&svc_ctx->tcb_list_lock); - if (status != 0) - ErrPrint("Error: %s\n", strerror(status)); status = pthread_mutex_destroy(&svc_ctx->packet_list_lock); if (status != 0) ErrPrint("Error: %s\n", strerror(status)); - status = close(svc_ctx->evt_pipe[EVT_READ]); - if (status < 0) - ErrPrint("Error: %s\n", strerror(errno)); - status = close(svc_ctx->evt_pipe[EVT_WRITE]); - if (status < 0) - ErrPrint("Error: %s\n", strerror(errno)); + CLOSE_PIPE(svc_ctx->evt_pipe); + CLOSE_PIPE(svc_ctx->tcb_pipe); secure_socket_destroy_handle(svc_ctx->fd); free(svc_ctx); return NULL; @@ -604,11 +583,14 @@ HAPI struct service_context *service_common_create(const char *addr, int (*servi return svc_ctx; } +/*! + * \note + * MAIN THREAD + */ HAPI int service_common_destroy(struct service_context *svc_ctx) { int status; void *ret; - char evt_ch = EVT_END_CH; if (!svc_ctx) return -EINVAL; @@ -618,38 +600,27 @@ HAPI int service_common_destroy(struct service_context *svc_ctx) * Terminate server thread */ secure_socket_destroy_handle(svc_ctx->fd); - status = pthread_join(svc_ctx->thid, &ret); - if (status != 0) - ErrPrint("Join: %s\n", strerror(status)); - /*! - * \note - * Terminate all client threads. - */ - tcb_teminate_all(svc_ctx); - /* Emit a finish event */ - if (write(svc_ctx->evt_pipe[EVT_WRITE], &evt_ch, sizeof(evt_ch)) == sizeof(evt_ch)) - ErrPrint("write: %s\n", strerror(errno)); - - /* Waiting */ - status = pthread_join(svc_ctx->service_thid, &ret); + status = pthread_join(svc_ctx->server_thid, &ret); if (status != 0) ErrPrint("Join: %s\n", strerror(status)); - - status = pthread_mutex_destroy(&svc_ctx->tcb_list_lock); - if (status != 0) - ErrPrint("Unable to destroy a mutex: %s\n", strerror(status)); + else + DbgPrint("Thread returns: %d\n", (int)ret); status = pthread_mutex_destroy(&svc_ctx->packet_list_lock); if (status != 0) ErrPrint("Unable to destroy a mutex: %s\n", strerror(status)); - status = close(svc_ctx->evt_pipe[EVT_WRITE]); - status = close(svc_ctx->evt_pipe[EVT_READ]); + CLOSE_PIPE(svc_ctx->evt_pipe); + CLOSE_PIPE(svc_ctx->tcb_pipe); free(svc_ctx); return 0; } +/*! + * \note + * SERVER THREAD + */ HAPI int tcb_fd(struct tcb *tcb) { if (!tcb) @@ -658,6 +629,10 @@ HAPI int tcb_fd(struct tcb *tcb) return tcb->fd; } +/*! + * \note + * SERVER THREAD + */ HAPI int tcb_client_type(struct tcb *tcb) { if (!tcb) @@ -666,15 +641,24 @@ HAPI int tcb_client_type(struct tcb *tcb) return tcb->type; } +/*! + * \note + * SERVER THREAD + */ HAPI int tcb_client_type_set(struct tcb *tcb, enum tcb_type type) { if (!tcb) return -EINVAL; + DbgPrint("TCB[%p] Client type is changed to %d from %d\n", tcb, type, tcb->type); tcb->type = type; return 0; } +/*! + * \note + * SERVER THREAD + */ HAPI struct service_context *tcb_svc_ctx(struct tcb *tcb) { if (!tcb) @@ -683,14 +667,26 @@ HAPI struct service_context *tcb_svc_ctx(struct tcb *tcb) return tcb->svc_ctx; } +/*! + * \note + * SERVER THREAD + */ HAPI int service_common_unicast_packet(struct tcb *tcb, struct packet *packet) { + struct service_context *svc_ctx; if (!tcb || !packet) return -EINVAL; + svc_ctx = tcb->svc_ctx; + + DbgPrint("Unicast packet\n"); return secure_socket_send(tcb->fd, (void *)packet_data(packet), packet_size(packet)); } +/*! + * \note + * SERVER THREAD + */ HAPI int service_common_multicast_packet(struct tcb *tcb, struct packet *packet, int type) { Eina_List *l; @@ -703,17 +699,18 @@ HAPI int service_common_multicast_packet(struct tcb *tcb, struct packet *packet, svc_ctx = tcb->svc_ctx; - CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock); + DbgPrint("Multicasting packets\n"); EINA_LIST_FOREACH(svc_ctx->tcb_list, l, target) { - if (target == tcb || target->type != type) + if (target == tcb || target->type != type) { + DbgPrint("Skip target: %p(%d) == %p/%d\n", target, target->type, tcb, type); continue; + } ret = secure_socket_send(target->fd, (void *)packet_data(packet), packet_size(packet)); if (ret < 0) ErrPrint("Failed to send packet: %d\n", ret); } - CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock); - + DbgPrint("Finish to multicast packet\n"); return 0; } diff --git a/src/setting.c b/src/setting.c index 8eaceca..c013a22 100644 --- a/src/setting.c +++ b/src/setting.c @@ -99,7 +99,12 @@ HAPI int setting_fini(void) { int ret; ret = vconf_ignore_key_changed(VCONFKEY_PM_STATE, lcd_state_cb); + if (ret < 0) + ErrPrint("Failed to ignore vconf key (%d)\n", ret); + ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, power_off_cb); + if (ret < 0) + ErrPrint("Failed to ignore vconf key (%d)\n", ret); return ret; } diff --git a/src/shortcut_service.c b/src/shortcut_service.c index 774d814..f2339a1 100644 --- a/src/shortcut_service.c +++ b/src/shortcut_service.c @@ -26,6 +26,7 @@ #include "service_common.h" #include "debug.h" #include "util.h" +#include "conf.h" #define SHORTCUT_ADDR "/tmp/.shortcut.service" @@ -93,24 +94,19 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat { const char *command; + DbgPrint("TCB: %p, Packet: %p\n", tcb, packet); + command = packet_command(packet); if (!command) { ErrPrint("Invalid command\n"); return -EINVAL; } + DbgPrint("Command: %s, Packet type[%d]\n", command, packet_type(packet)); switch (packet_type(packet)) { case PACKET_REQ: /* Need to send reply packet */ DbgPrint("REQ: Command: [%s]\n", command); - if (!strcmp(command, "register_service")) { - /*! - * To multicast event packets to the service clients - */ - tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE); - break; - } - if (service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE) < 0) ErrPrint("Unable to send service request packet\n"); else @@ -119,7 +115,7 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat case PACKET_REQ_NOACK: /* Doesn't need to send reply packet */ DbgPrint("REQ_NOACK: Command: [%s]\n", command); - if (!strcmp(command, "register_service")) { + if (!strcmp(command, "service_register")) { tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE); break; } @@ -157,7 +153,7 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat * Do not try to do anyother operation in these functions */ -int service_shortcut_init(void) +HAPI int shortcut_service_init(void) { if (s_info.svc_ctx) { ErrPrint("Already initialized\n"); @@ -165,18 +161,22 @@ int service_shortcut_init(void) } s_info.svc_ctx = service_common_create(SHORTCUT_ADDR, service_thread_main, NULL); - if (!s_info.svc_ctx) + if (!s_info.svc_ctx) { + ErrPrint("Unable to activate service thread\n"); return LB_STATUS_ERROR_FAULT; + } + DbgPrint("Successfully initiated\n"); return LB_STATUS_SUCCESS; } -int service_shortcut_fini(void) +HAPI int shortcut_service_fini(void) { if (!s_info.svc_ctx) return LB_STATUS_ERROR_INVALID; service_common_destroy(s_info.svc_ctx); + DbgPrint("Successfully Finalized\n"); return LB_STATUS_SUCCESS; } |