diff --git a/mongoose.c b/mongoose.c index b01b6212..c21693e8 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4017,8 +4017,8 @@ struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds, unsigned flags, void (*fn)(void *), void *arg) { struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t)); if (t != NULL) { + flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg); - t->id = mgr->timerid++; } return t; } @@ -9131,11 +9131,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, 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; *head = t; } @@ -9166,6 +9164,12 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) { t->fn(t->arg); } 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); + } } } diff --git a/mongoose.h b/mongoose.h index b019dea8..a9313e0b 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1020,16 +1020,17 @@ void mg_log_set_fn(mg_pfn_t fn, void *param); struct mg_timer { - unsigned long id; // Timer ID - uint64_t period_ms; // Timer period in milliseconds - uint64_t expire; // Expiration timestamp in milliseconds - unsigned flags; // Possible flags values below -#define MG_TIMER_ONCE 0 // Call function once -#define MG_TIMER_REPEAT 1 // Call function periodically -#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set - void (*fn)(void *); // Function to call - void *arg; // Function argument - struct mg_timer *next; // Linkage + uint64_t period_ms; // Timer period in milliseconds + uint64_t expire; // Expiration timestamp in milliseconds + unsigned flags; // Possible flags values below +#define MG_TIMER_ONCE 0 // Call function once +#define MG_TIMER_REPEAT 1 // Call function periodically +#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set +#define MG_TIMER_CALLED 4 // Timer function was called at least once +#define MG_TIMER_AUTODELETE 8 // free() timer when done + void (*fn)(void *); // Function to call + void *arg; // Function argument + struct mg_timer *next; // Linkage }; void mg_timer_init(struct mg_timer **head, struct mg_timer *timer, @@ -2208,7 +2209,6 @@ struct mg_mgr { int dnstimeout; // DNS resolve timeout in milliseconds bool use_dns6; // Use DNS6 server by default, see #1532 unsigned long nextid; // Next connection ID - unsigned long timerid; // Next timer ID void *userdata; // Arbitrary user data pointer void *tls_ctx; // TLS context shared by all TLS sessions uint16_t mqtt_id; // MQTT IDs for pub/sub diff --git a/src/net.c b/src/net.c index 2bc12c41..deab43c9 100644 --- a/src/net.c +++ b/src/net.c @@ -1,7 +1,7 @@ -#include "net.h" #include "dns.h" #include "fmt.h" #include "log.h" +#include "net.h" #include "printf.h" #include "profile.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) { struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t)); if (t != NULL) { + flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg); - t->id = mgr->timerid++; } return t; } diff --git a/src/net.h b/src/net.h index 08d0893c..2fc5a059 100644 --- a/src/net.h +++ b/src/net.h @@ -27,7 +27,6 @@ struct mg_mgr { int dnstimeout; // DNS resolve timeout in milliseconds bool use_dns6; // Use DNS6 server by default, see #1532 unsigned long nextid; // Next connection ID - unsigned long timerid; // Next timer ID void *userdata; // Arbitrary user data pointer void *tls_ctx; // TLS context shared by all TLS sessions uint16_t mqtt_id; // MQTT IDs for pub/sub diff --git a/src/timer.c b/src/timer.c index dc05c79e..e747b667 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,11 +1,9 @@ -#include "timer.h" #include "arch.h" - -#define MG_TIMER_CALLED 4 +#include "timer.h" void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms, 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; *head = t; } @@ -36,5 +34,11 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) { t->fn(t->arg); } 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); + } } } diff --git a/src/timer.h b/src/timer.h index 8e78ba75..effc34c3 100644 --- a/src/timer.h +++ b/src/timer.h @@ -3,16 +3,17 @@ #include "arch.h" struct mg_timer { - unsigned long id; // Timer ID - uint64_t period_ms; // Timer period in milliseconds - uint64_t expire; // Expiration timestamp in milliseconds - unsigned flags; // Possible flags values below -#define MG_TIMER_ONCE 0 // Call function once -#define MG_TIMER_REPEAT 1 // Call function periodically -#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set - void (*fn)(void *); // Function to call - void *arg; // Function argument - struct mg_timer *next; // Linkage + uint64_t period_ms; // Timer period in milliseconds + uint64_t expire; // Expiration timestamp in milliseconds + unsigned flags; // Possible flags values below +#define MG_TIMER_ONCE 0 // Call function once +#define MG_TIMER_REPEAT 1 // Call function periodically +#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set +#define MG_TIMER_CALLED 4 // Timer function was called at least once +#define MG_TIMER_AUTODELETE 8 // free() timer when done + void (*fn)(void *); // Function to call + void *arg; // Function argument + struct mg_timer *next; // Linkage }; void mg_timer_init(struct mg_timer **head, struct mg_timer *timer, diff --git a/test/unit_test.c b/test/unit_test.c index 90dcc5da..1ca16e3d 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1960,6 +1960,22 @@ static void test_timer(void) { ASSERT(mgr.timers == 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, ...) {