[FIX] replay thread cancellation
authorNikita Kalyazin <n.kalyazin@samsung.com>
Tue, 2 Jul 2013 07:23:22 +0000 (11:23 +0400)
committerNikita Kalyazin <n.kalyazin@samsung.com>
Tue, 2 Jul 2013 07:23:22 +0000 (11:23 +0400)
Also:
 - build warnings;
 - start and stop when primary app appears and disappears.

daemon/da_protocol.c
daemon/da_protocol.h
daemon/daemon.c
daemon/threads.c

index 8bc0457..b96a8f1 100644 (file)
@@ -645,6 +645,14 @@ static char *parse_replay_event(char *buf,
        return p;
 }
 
+void reset_replay_event_seq(struct replay_event_seq_t *res)
+{
+       res->enabled = 0;
+       res->tv = (struct timeval){0, 0};
+       res->event_num = 0;
+       free(res->events);
+}
+
 static char *parse_replay_event_seq(char *buf,
                                    struct replay_event_seq_t *res)
 {
index 210440e..2060f4c 100644 (file)
@@ -339,7 +339,10 @@ void free_msg_data(struct msg_data_t *msg);
 void free_msg_payload(struct msg_t *msg);
 void free_sys_info(struct system_info_t *sys_info);
 int start_replay();
+void stop_replay();
+
 void reset_msg(struct msg_t *msg);
+void reset_replay_event_seq(struct replay_event_seq_t *res);
 
 extern struct prof_session_t prof_session;
 
index 6d4b5dc..9d8a61d 100644 (file)
@@ -367,11 +367,6 @@ int startProfiling(long launchflag)
                break;
        }
 
-       if (start_replay() != 0) {
-               LOGE("Cannot start replay thread\n");
-               return -1;
-       }
-
        return 0;
 }
 
@@ -780,14 +775,24 @@ static int targetEventHandler(int epollfd, int index, uint64_t msg)
 {
        if(msg & EVENT_PID)
        {
+               if (index == 0) { // main application
+                       if (start_replay() != 0) {
+                               LOGE("Cannot start replay thread\n");
+                               return -1;
+                       }
+               }
                manager.target[index].initial_log = 1;
        }
 
        if(msg & EVENT_STOP || msg & EVENT_ERROR)
        {
                LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n",
-                               manager.target[index].socket, manager.target[index].pid, manager.target_count - 1);
-
+                    manager.target[index].socket,
+                    manager.target[index].pid,
+                    manager.target_count - 1);
+               if (index == 0) { // main application
+                       stop_replay();
+               }
                epoll_ctl(epollfd, EPOLL_CTL_DEL, manager.target[index].event_fd, NULL);
                setEmptyTargetSlot(index);
                if (0 == __sync_sub_and_fetch(&manager.target_count, 1)) // all target client are closed
index 9e4d496..05781d3 100644 (file)
@@ -287,15 +287,60 @@ void* samplingThread(void* data)
        return NULL;
 }
 
+// return 0 if normal case
+// return minus value if critical error
+// return plus value if non-critical error
+int samplingStart()
+{
+       struct itimerval timerval;
+
+       if(manager.sampling_thread != -1)       // already started
+               return 1;
+
+       if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
+       {
+               LOGE("Failed to create sampling thread\n");
+               return -1;
+       }
+
+       timerval.it_interval.tv_sec = TIMER_INTERVAL_SEC;
+       timerval.it_interval.tv_usec = TIMER_INTERVAL_USEC;
+       timerval.it_value.tv_sec = TIMER_INTERVAL_SEC;
+       timerval.it_value.tv_usec = TIMER_INTERVAL_USEC;
+       setitimer(ITIMER_REAL, &timerval, NULL);
+
+       return 0;
+}
+
+int samplingStop()
+{
+       if(manager.sampling_thread != -1)
+       {
+               struct itimerval stopval;
+
+               // stop timer
+               stopval.it_interval.tv_sec = 0;
+               stopval.it_interval.tv_usec = 0;
+               stopval.it_value.tv_sec = 0;
+               stopval.it_value.tv_usec = 0;
+               setitimer(ITIMER_REAL, &stopval, NULL);
+
+               pthread_kill(manager.sampling_thread, SIGUSR1);
+               pthread_join(manager.sampling_thread, NULL);
+
+               manager.sampling_thread = -1;
+       }
+
+       return 0;
+}
+
 static useconds_t time_diff_us(struct timeval *tv1, struct timeval *tv2)
 {
        return (tv1->tv_sec - tv2->tv_sec) * 1000000 +
                ((int)tv1->tv_usec - (int)tv2->tv_usec);
 }
 
-/* TODO: find a way to stop the thread
-   before it playbacks all the events */
-void *replay_thread(void *arg)
+static void *replay_thread(void *arg)
 {
        struct replay_event_seq_t *event_seq = (struct replay_event_seq_t *)arg;
        int i = 0;
@@ -350,63 +395,15 @@ void *replay_thread(void *arg)
        return arg;
 }
 
-// return 0 if normal case
-// return minus value if critical error
-// return plus value if non-critical error
-int samplingStart()
-{
-       struct itimerval timerval;
-
-       if(manager.sampling_thread != -1)       // already started
-               return 1;
-
-       if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
-       {
-               LOGE("Failed to create sampling thread\n");
-               return -1;
-       }
-
-       timerval.it_interval.tv_sec = TIMER_INTERVAL_SEC;
-       timerval.it_interval.tv_usec = TIMER_INTERVAL_USEC;
-       timerval.it_value.tv_sec = TIMER_INTERVAL_SEC;
-       timerval.it_value.tv_usec = TIMER_INTERVAL_USEC;
-       setitimer(ITIMER_REAL, &timerval, NULL);
-
-       return 0;
-}
-
-int samplingStop()
-{
-       if(manager.sampling_thread != -1)
-       {
-               struct itimerval stopval;
-
-               // stop timer
-               stopval.it_interval.tv_sec = 0;
-               stopval.it_interval.tv_usec = 0;
-               stopval.it_value.tv_sec = 0;
-               stopval.it_value.tv_usec = 0;
-               setitimer(ITIMER_REAL, &stopval, NULL);
-
-               pthread_kill(manager.sampling_thread, SIGUSR1);
-               pthread_join(manager.sampling_thread, NULL);
-
-               manager.sampling_thread = -1;
-       }
-
-       return 0;
-}
-
 int start_replay()
 {
        if (manager.replay_thread != -1) // already started
                return 1;
 
-       // TODO: non-joinable thread
-       if(pthread_create(&(manager.replay_thread),
-                         NULL,
-                         replay_thread,
-                         &prof_session.replay_event_seq) < 0)
+       if (pthread_create(&(manager.replay_thread),
+                          NULL,
+                          replay_thread,
+                          &prof_session.replay_event_seq) < 0)
        {
                LOGE("Failed to create replay thread\n");
                return 1;
@@ -414,3 +411,16 @@ int start_replay()
 
        return 0;
 }
+
+void stop_replay()
+{
+       if (manager.replay_thread == -1) {
+               LOGI("replay thread not running\n");
+               return;
+       }
+       LOGI("stopping replay thread\n");
+       pthread_cancel(manager.replay_thread);
+       pthread_join(manager.replay_thread, NULL);
+       reset_replay_event_seq(&prof_session.replay_event_seq);
+       LOGI("replay thread joined\n");
+}