timer: Fix stopping a running timer 75/23475/2 8.99.5 icefish/8.99.5 icefish_8.99.5
authorRomain Forlot <romain.forlot@iot.bzh>
Fri, 27 Dec 2019 13:30:27 +0000 (14:30 +0100)
committerRomain Forlot <romain.forlot@iot.bzh>
Fri, 10 Jan 2020 10:54:34 +0000 (11:54 +0100)
This fix a bug where using 1 don't stop the timer to trigger
and now TimerStop really stop the timer...
sd_event_source_unref only decrement the ref counter of the
sd_event_source. If we want to stop returning -1 in the callback
will make sure we effectively stop the timer instead of only
decrement the ref counter.

Bug-AGL: SPEC-3073

Change-Id: I4619ff1695c398a7c9683b58bd193b8c21b9abb1
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
afb-timer.c

index 4afdb0e..33d1b0a 100644 (file)
@@ -36,34 +36,29 @@ static int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
     int done;
     uint64_t usec;
 
+    // Stop Timer when count is null
+    if (timerHandle->count-- == 0) {
+        if (timerHandle->freeCB) timerHandle->freeCB(timerHandle->context);
+        free (timerHandle);
+        return -1;
+    }
+
     done= timerHandle->callback(timerHandle);
     if (!done) {
         AFB_API_WARNING(timerHandle->api, "TimerNext Callback Fail Tag=%s", timerHandle->uid);
         return -1;
     }
 
-    // Rearm timer if needed
-    timerHandle->count --;
-    if (timerHandle->count == 0) {
-        sd_event_source_unref(source);
-        if (timerHandle->freeCB) timerHandle->freeCB(timerHandle->context);
-        free (handle);
-        return 0;
-    }
-    else {
-        // otherwise validate timer for a new run
-        sd_event_now(afb_api_get_event_loop(timerHandle->api), CLOCK_MONOTONIC, &usec);
-        sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
-        sd_event_source_set_time(source, usec + timerHandle->delay*1000);
-    }
+    // otherwise validate timer for a new run
+    sd_event_now(afb_api_get_event_loop(timerHandle->api), CLOCK_MONOTONIC, &usec);
+    sd_event_source_set_time(source, usec + timerHandle->delay*1000);
+    sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
 
     return 0;
 }
 
 void TimerEvtStop(TimerHandleT *timerHandle) {
-    sd_event_source_unref(timerHandle->evtSource);
-    if (timerHandle->freeCB) timerHandle->freeCB(timerHandle->context);
-    free (timerHandle);
+    timerHandle->count = 0; // Force timer to close
 }
 
 void TimerEvtStart(afb_api_t api, TimerHandleT *timerHandle, timerCallbackT callback, void *context) {
@@ -76,7 +71,7 @@ void TimerEvtStart(afb_api_t api, TimerHandleT *timerHandle, timerCallbackT call
 
     // set a timer with ~250us accuracy
     sd_event_now(afb_api_get_event_loop(api), CLOCK_MONOTONIC, &usec);
-    sd_event_add_time(afb_api_get_event_loop(api), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay*1000, 250, TimerNext, timerHandle);
+    sd_event_add_time(afb_api_get_event_loop(api), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay*1000, 0, TimerNext, timerHandle);
 }
 
 uint64_t LockWait(afb_api_t api, uint64_t utimeout) {