Merge pull request #3100 from cesanta/timers

Fix #2768 - remove completed timers
This commit is contained in:
Sergey Lyubka authored and GitHub committed 2025-04-14 15:15:36 +01:00
commit fb6c6aafeb
7 files changed
+56 -32

No files matched your search

+8 -4
View File
@@ -4017,8 +4017,8 @@ struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
unsigned flags, void (*fn)(void *), void *arg) { unsigned flags, void (*fn)(void *), void *arg) {
struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t)); struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
if (t != NULL) { if (t != NULL) {
flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg); mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
t->id = mgr->timerid++;
} }
return t; return t;
} }
@@ -9135,11 +9135,9 @@ bool mg_str_to_num(struct mg_str str, int base, void *val, size_t val_len) {
#define MG_TIMER_CALLED 4
void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms, void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms,
unsigned flags, void (*fn)(void *), void *arg) { unsigned flags, void (*fn)(void *), void *arg) {
t->id = 0, t->period_ms = ms, t->expire = 0; t->period_ms = ms, t->expire = 0;
t->flags = flags, t->fn = fn, t->arg = arg, t->next = *head; t->flags = flags, t->fn = fn, t->arg = arg, t->next = *head;
*head = t; *head = t;
} }
@@ -9170,6 +9168,12 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
t->fn(t->arg); t->fn(t->arg);
} }
t->flags |= MG_TIMER_CALLED; t->flags |= MG_TIMER_CALLED;
// If this timer is not repeating and marked AUTODELETE, remove it
if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
mg_timer_free(head, t);
free(t);
}
} }
} }
+11 -11
View File
@@ -1043,16 +1043,17 @@ void mg_log_set_fn(mg_pfn_t fn, void *param);
struct mg_timer { struct mg_timer {
unsigned long id; // Timer ID uint64_t period_ms; // Timer period in milliseconds
uint64_t period_ms; // Timer period in milliseconds uint64_t expire; // Expiration timestamp in milliseconds
uint64_t expire; // Expiration timestamp in milliseconds unsigned flags; // Possible flags values below
unsigned flags; // Possible flags values below #define MG_TIMER_ONCE 0 // Call function once
#define MG_TIMER_ONCE 0 // Call function once #define MG_TIMER_REPEAT 1 // Call function periodically
#define MG_TIMER_REPEAT 1 // Call function periodically #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set #define MG_TIMER_CALLED 4 // Timer function was called at least once
void (*fn)(void *); // Function to call #define MG_TIMER_AUTODELETE 8 // free() timer when done
void *arg; // Function argument void (*fn)(void *); // Function to call
struct mg_timer *next; // Linkage void *arg; // Function argument
struct mg_timer *next; // Linkage
}; };
void mg_timer_init(struct mg_timer **head, struct mg_timer *timer, void mg_timer_init(struct mg_timer **head, struct mg_timer *timer,
@@ -2232,7 +2233,6 @@ struct mg_mgr {
int dnstimeout; // DNS resolve timeout in milliseconds int dnstimeout; // DNS resolve timeout in milliseconds
bool use_dns6; // Use DNS6 server by default, see #1532 bool use_dns6; // Use DNS6 server by default, see #1532
unsigned long nextid; // Next connection ID unsigned long nextid; // Next connection ID
unsigned long timerid; // Next timer ID
void *userdata; // Arbitrary user data pointer void *userdata; // Arbitrary user data pointer
void *tls_ctx; // TLS context shared by all TLS sessions void *tls_ctx; // TLS context shared by all TLS sessions
uint16_t mqtt_id; // MQTT IDs for pub/sub uint16_t mqtt_id; // MQTT IDs for pub/sub
+2 -2
View File
@@ -1,7 +1,7 @@
#include "net.h"
#include "dns.h" #include "dns.h"
#include "fmt.h" #include "fmt.h"
#include "log.h" #include "log.h"
#include "net.h"
#include "printf.h" #include "printf.h"
#include "profile.h" #include "profile.h"
#include "timer.h" #include "timer.h"
@@ -218,8 +218,8 @@ struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
unsigned flags, void (*fn)(void *), void *arg) { unsigned flags, void (*fn)(void *), void *arg) {
struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t)); struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
if (t != NULL) { if (t != NULL) {
flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg); mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
t->id = mgr->timerid++;
} }
return t; return t;
} }
-1
View File
@@ -27,7 +27,6 @@ struct mg_mgr {
int dnstimeout; // DNS resolve timeout in milliseconds int dnstimeout; // DNS resolve timeout in milliseconds
bool use_dns6; // Use DNS6 server by default, see #1532 bool use_dns6; // Use DNS6 server by default, see #1532
unsigned long nextid; // Next connection ID unsigned long nextid; // Next connection ID
unsigned long timerid; // Next timer ID
void *userdata; // Arbitrary user data pointer void *userdata; // Arbitrary user data pointer
void *tls_ctx; // TLS context shared by all TLS sessions void *tls_ctx; // TLS context shared by all TLS sessions
uint16_t mqtt_id; // MQTT IDs for pub/sub uint16_t mqtt_id; // MQTT IDs for pub/sub
+8 -4
View File
@@ -1,11 +1,9 @@
#include "timer.h"
#include "arch.h" #include "arch.h"
#include "timer.h"
#define MG_TIMER_CALLED 4
void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms, void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms,
unsigned flags, void (*fn)(void *), void *arg) { unsigned flags, void (*fn)(void *), void *arg) {
t->id = 0, t->period_ms = ms, t->expire = 0; t->period_ms = ms, t->expire = 0;
t->flags = flags, t->fn = fn, t->arg = arg, t->next = *head; t->flags = flags, t->fn = fn, t->arg = arg, t->next = *head;
*head = t; *head = t;
} }
@@ -36,5 +34,11 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
t->fn(t->arg); t->fn(t->arg);
} }
t->flags |= MG_TIMER_CALLED; t->flags |= MG_TIMER_CALLED;
// If this timer is not repeating and marked AUTODELETE, remove it
if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
mg_timer_free(head, t);
free(t);
}
} }
} }
+11 -10
View File
@@ -3,16 +3,17 @@
#include "arch.h" #include "arch.h"
struct mg_timer { struct mg_timer {
unsigned long id; // Timer ID uint64_t period_ms; // Timer period in milliseconds
uint64_t period_ms; // Timer period in milliseconds uint64_t expire; // Expiration timestamp in milliseconds
uint64_t expire; // Expiration timestamp in milliseconds unsigned flags; // Possible flags values below
unsigned flags; // Possible flags values below #define MG_TIMER_ONCE 0 // Call function once
#define MG_TIMER_ONCE 0 // Call function once #define MG_TIMER_REPEAT 1 // Call function periodically
#define MG_TIMER_REPEAT 1 // Call function periodically #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set #define MG_TIMER_CALLED 4 // Timer function was called at least once
void (*fn)(void *); // Function to call #define MG_TIMER_AUTODELETE 8 // free() timer when done
void *arg; // Function argument void (*fn)(void *); // Function to call
struct mg_timer *next; // Linkage void *arg; // Function argument
struct mg_timer *next; // Linkage
}; };
void mg_timer_init(struct mg_timer **head, struct mg_timer *timer, void mg_timer_init(struct mg_timer **head, struct mg_timer *timer,
+16
View File
@@ -1960,6 +1960,22 @@ static void test_timer(void) {
ASSERT(mgr.timers == NULL); ASSERT(mgr.timers == NULL);
ASSERT(mgr.conns == NULL); ASSERT(mgr.conns == NULL);
} }
// Test that non-repeating called timers are deleted, see #2768
{
struct mg_mgr mgr;
int arg = 0;
mg_mgr_init(&mgr);
mg_timer_add(&mgr, 0, MG_TIMER_ONCE, f1, &arg);
ASSERT(mgr.timers != NULL);
mg_mgr_poll(&mgr, 10);
ASSERT(arg == 1);
ASSERT(mgr.timers == NULL);
mg_mgr_free(&mgr);
ASSERT(mgr.timers == NULL);
ASSERT(mgr.conns == NULL);
}
} }
static bool sn(const char *fmt, ...) { static bool sn(const char *fmt, ...) {