Hi,

this is a very raw ugly patch that fix the deadlock when the user would like to stop the GPS. The patch is powered enable only when the user require a START command. I have done some test.


Michael
diff --git a/gps_freerunner.c b/gps_freerunner.c
index 186e592..9cab5a3 100644
--- a/gps_freerunner.c
+++ b/gps_freerunner.c
@@ -19,11 +19,11 @@
 
 #define  GPS_DEBUG  0
 
-#define  DFR(...)   LOGD(__VA_ARGS__)
-
 #if GPS_DEBUG
+#  define  DFR(...)   LOGD(__VA_ARGS__)
 #  define  D(...)   LOGD(__VA_ARGS__)
 #else
+#  define  DFR(...) ((void)0)
 #  define  D(...)   ((void)0)
 #endif
 
@@ -838,9 +838,11 @@ gps_state_start( GpsState*  s )
     char  cmd = CMD_START;
     int   ret;
 
-    do { ret=write( s->control[0], &cmd, 1 ); }
+    do { ret = write( s->control[0], &cmd, 1 ); }
     while (ret < 0 && errno == EINTR);
 
+    D("GPS start request");
+
     if (ret != 1)
         D("%s: could not send CMD_START command: ret=%d: %s",
           __FUNCTION__, ret, strerror(errno));
@@ -853,6 +855,8 @@ gps_state_stop( GpsState*  s )
     char  cmd = CMD_STOP;
     int   ret;
 
+    D("GPS stop request");
+
     do { ret=write( s->control[0], &cmd, 1 ); }
     while (ret < 0 && errno == EINTR);
 
@@ -863,19 +867,18 @@ gps_state_stop( GpsState*  s )
 
 
 static int
-epoll_register( int  epoll_fd, int  fd )
+epoll_register( int  epoll_fd, int  fd, struct epoll_event *ev)
 {
-    struct epoll_event  ev;
     int                 ret, flags;
 
     /* important: make the fd non-blocking */
     flags = fcntl(fd, F_GETFL);
     fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 
-    ev.events  = EPOLLIN;
-    ev.data.fd = fd;
+    ev->events  = EPOLLIN;
+    ev->data.fd = fd;
     do {
-        ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
+        ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, ev );
     } while (ret < 0 && errno == EINTR);
     return ret;
 }
@@ -900,25 +903,21 @@ gps_state_thread( void*  arg )
 {
     GpsState*   state = (GpsState*) arg;
     NmeaReader  *reader;
-    int         epoll_fd   = epoll_create(2);
-    int         started    = 0;
-    int         gps_fd     = state->fd;
-    int         control_fd = state->control[1];
+    struct epoll_event  ev[2];
+    int                 epoll_fd   = epoll_create(2);
+    int                 started    = 0;
+    int                 gps_fd     = state->fd;
+    int                 control_fd = state->control[1];
 
     reader = &state->reader;
 
     nmea_reader_init( reader );
 
     // register control file descriptors for polling
-    epoll_register( epoll_fd, control_fd );
-    epoll_register( epoll_fd, gps_fd );
+    epoll_register( epoll_fd, control_fd, &ev[0] );
 
     D("gps thread running");
 
-    gps_dev_init(gps_fd);
-
-    GPS_STATUS_CB(state->callbacks, GPS_STATUS_ENGINE_ON); 
-
     // now loop
     for (;;) {
         struct epoll_event   events[2];
@@ -930,7 +929,6 @@ gps_state_thread( void*  arg )
                 LOGE("epoll_wait() unexpected error: %s", strerror(errno));
             continue;
         }
-        D("gps thread received %d events", nevents);
         for (ne = 0; ne < nevents; ne++) {
             if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
                 LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
@@ -956,12 +954,13 @@ gps_state_thread( void*  arg )
                         if (!started) {
                             D("gps thread starting  location_cb=%p", state->callbacks.location_cb);
                             started = 1;
-
+                            gps_dev_init(gps_fd);
                             gps_dev_start(gps_fd);
 
                             GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_BEGIN);
 
                             state->init = STATE_START;
+			    epoll_register( epoll_fd, gps_fd, &ev[1] );
 
                             if ( pthread_create( &state->tmr_thread, NULL, gps_timer_thread, state ) != 0 ) {
                                 LOGE("could not create gps timer thread: %s", strerror(errno));
@@ -979,10 +978,12 @@ gps_state_thread( void*  arg )
                             started = 0;
 
                             gps_dev_stop(gps_fd);
+                            gps_dev_deinit(gps_fd);
 
                             state->init = STATE_INIT;
 
                             pthread_join(state->tmr_thread, &dummy);
+                            epoll_deregister(epoll_fd, gps_fd);
 
                             GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_END);
 
@@ -991,24 +992,16 @@ gps_state_thread( void*  arg )
                 }
                 else if (fd == gps_fd)
                 {
-                    char  buff[32];
-                    D("gps fd event");
-                    for (;;) {
-                        int  nn, ret;
-
-                        ret = read( fd, buff, sizeof(buff) );
-                        if (ret < 0) {
-                            if (errno == EINTR)
-                                continue;
-                            if (errno != EWOULDBLOCK)
-                                LOGE("error while reading from gps daemon socket: %s:", strerror(errno));
-                            break;
-                        }
+                    char  buff[1024];
+                    int  nn, ret;
+
+                    ret = read( fd, buff, sizeof(buff) );
+                    if (ret > 0) {
                         D("received %d bytes: %.*s", ret, ret, buff);
                         for (nn = 0; nn < ret; nn++)
                             nmea_reader_addc( reader, buff[nn] );
+                        D("gps fd event end");
                     }
-                    D("gps fd event end");
                 }
                 else
                 {
@@ -1021,8 +1014,6 @@ Exit:
 
     gps_dev_deinit(gps_fd);
 
-    GPS_STATUS_CB(state->callbacks, GPS_STATUS_ENGINE_OFF);
-
     return NULL;
 }
 
@@ -1031,30 +1022,12 @@ gps_timer_thread( void*  arg )
 {
 
   GpsState *state = (GpsState *)arg;
-  pthread_mutex_t timer_mtx;
-  pthread_cond_t  timer_cond;
   struct timespec to;
 
   DFR("gps entered timer thread");
 
-  pthread_mutex_init(&timer_mtx, NULL);
-  pthread_cond_init(&timer_cond, NULL);
-
   do {
 
-    clock_gettime(CLOCK_MONOTONIC, &to);
-
-    if (state->fix_freq > 0) {
-      to.tv_sec += state->fix_freq;
-    } else {
-      to.tv_sec++;
-    }
-
-    pthread_mutex_lock(&timer_mtx);
-
-    // binoic specific function - non POSIX */
-    pthread_cond_timedwait_monotonic(&timer_cond, &timer_mtx, &to);
-
     DFR ("gps timer exp");
 
     GPS_STATE_LOCK_FIX(state);
@@ -1087,14 +1060,10 @@ gps_timer_thread( void*  arg )
     }
 
     GPS_STATE_UNLOCK_FIX(state);
-
-    pthread_mutex_unlock(&timer_mtx);
+    sleep(state->fix_freq);
 
   } while(state->init == STATE_START);
 
-  pthread_mutex_destroy(&timer_mtx);
-  pthread_cond_destroy(&timer_cond);
-
   DFR("gps timer thread destroyed");
 
   return NULL;
@@ -1255,7 +1224,7 @@ freerunner_gps_set_fix_frequency(int freq)
 
     DFR("%s: called", __FUNCTION__);
 
-    s->fix_freq = freq;
+    s->fix_freq = (freq <= 0) ? 1 : freq;
 
     DFR("gps fix frquency set to %d secs", freq);
 }
_______________________________________________
android-freerunner mailing list
[email protected]
http://android.koolu.org/listinfo.cgi/android-freerunner-koolu.org

Reply via email to