include/fsm.h, src/fsm/*: reworked memory management of the logging system
This commits reworks the way that memory is allocated for the logging system. We basically use a double-linked list, with the oldest and the latest elements stored in a static variable. Most recent log entries are added at the latest position in this structure. A new function to clear and free a log unit has been implemented, and can be used at many points. We take care that each log unit is freed at closing time. Also, fsm docs have been a bit clarified. Tested with valgrind: ==6161== LEAK SUMMARY: ==6161== definitely lost: 5,008 bytes in 54 blocks ==6161== indirectly lost: 16,119 bytes in 672 blocks We can consider that as a basis for future work, as these leaks are due to external causes (e.g. libraries). Signed-off-by: Jean Sirmai <jean@a-lec.org> Signed-off-by: Adrien Bourmault <neox@a-lec.org>
This commit is contained in:
parent
4c375c5405
commit
fcc2dd1c6e
|
@ -177,30 +177,26 @@ enum fsm_enum_log_source {
|
||||||
/**
|
/**
|
||||||
* A log unit must include the followings:
|
* A log unit must include the followings:
|
||||||
*
|
*
|
||||||
* @callergraph
|
* @see fsm_log_t
|
||||||
* @see fsm_log_struct
|
|
||||||
*/
|
*/
|
||||||
typedef struct fsm_log_unit_struct
|
struct fsm_log_unit_t
|
||||||
{
|
{
|
||||||
long yy_dd_mm; /**< * date of the event reported in the log */
|
long yy_dd_mm; /**< * date of the event reported in the log */
|
||||||
long usec; /**< * with microseconds precision */
|
long usec; /**< * with microseconds precision */
|
||||||
char *file_source; /**< * emitter file */
|
char *file_source; /**< * emitter file */
|
||||||
char *function_source; /**< * emitter function */
|
char *function_source; /**< * emitter function */
|
||||||
char *string_value; /**< * any event descriptors */
|
char *string_value; /**< * any event descriptors */
|
||||||
struct fsm_log_unit_struct *prev; /**< * chained list */
|
struct fsm_log_unit_t *prev; /**< * chained list */
|
||||||
struct fsm_log_unit_struct *next; /**< * chained list */
|
struct fsm_log_unit_t *next; /**< * chained list */
|
||||||
}
|
};
|
||||||
fsm_log_unit_struct;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log is a double-chained list. Two links towards the previous and the next unit
|
* Log is a double-chained list. Two links towards the previous and the next unit
|
||||||
* are required to initialize and manage it.
|
* are required to initialize and manage it.
|
||||||
*
|
*
|
||||||
* @callgraph
|
* @see fsm_log_t_unit
|
||||||
* @see fsm_log_struct_unit
|
|
||||||
*
|
*
|
||||||
* @callergraph
|
|
||||||
* @see fsm_init_log()
|
* @see fsm_init_log()
|
||||||
* @see fsm_publish_log()
|
* @see fsm_publish_log()
|
||||||
* @see fsm_clear_log()
|
* @see fsm_clear_log()
|
||||||
|
@ -209,30 +205,31 @@ typedef struct fsm_log_unit_struct
|
||||||
* @see fsm_seek_log()
|
* @see fsm_seek_log()
|
||||||
* @see fsm_remove_log()
|
* @see fsm_remove_log()
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
struct fsm_log_t
|
||||||
fsm_log_unit_struct *first; /**< * required */
|
{
|
||||||
fsm_log_unit_struct *last; /**< * required */
|
struct fsm_log_unit_t *oldest; /**< * required */
|
||||||
}
|
struct fsm_log_unit_t *latest; /**< * required */
|
||||||
fsm_log_struct;
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void fsm_init_log (fsm_log_struct *jj);
|
void fsm_init_log (struct fsm_log_t *);
|
||||||
void fsm_publish_log (fsm_log_struct jj);
|
void fsm_publish_log (struct fsm_log_t *);
|
||||||
void fsm_clear_log (fsm_log_struct *jj);
|
void fsm_clear_log (struct fsm_log_t *);
|
||||||
|
void fsm_clear_log_unit (struct fsm_log_unit_t *);
|
||||||
|
|
||||||
void fsm_add_log_event (fsm_log_struct *jj,
|
void fsm_add_log_event (struct fsm_log_t *gg_logs,
|
||||||
char *file_source,
|
char *file_source,
|
||||||
char *function_source,
|
char *function_source,
|
||||||
char *string_value);
|
char *string_value);
|
||||||
|
|
||||||
int fsm_get_log_length(fsm_log_struct jj);
|
int fsm_get_log_length(struct fsm_log_t *);
|
||||||
void fsm_seek_log (fsm_log_struct jj,
|
void fsm_seek_log (struct fsm_log_t *gg_logs,
|
||||||
long usec,
|
long usec,
|
||||||
char *file_source,
|
char *file_source,
|
||||||
char *function_source,
|
char *function_source,
|
||||||
char *string_value);
|
char *string_value);
|
||||||
long fsm_remove_log (fsm_log_struct *jj,
|
long fsm_remove_log (struct fsm_log_t *gg_logs,
|
||||||
char *file_source,
|
char *file_source,
|
||||||
char *function_source,
|
char *function_source,
|
||||||
char *string_value);
|
char *string_value);
|
||||||
|
@ -248,5 +245,3 @@ void fsm_relay_close_log();
|
||||||
|
|
||||||
void fsm_init (char *initial_message_from_main);
|
void fsm_init (char *initial_message_from_main);
|
||||||
void fsm_close (char *final_message_from_main);
|
void fsm_close (char *final_message_from_main);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,26 +39,35 @@
|
||||||
*
|
*
|
||||||
* @since 2024-09
|
* @since 2024-09
|
||||||
*
|
*
|
||||||
* @param *jj
|
* @param *gg_logs
|
||||||
* @param *file_source
|
* @param *file_source
|
||||||
* @param *function_source
|
* @param *function_source
|
||||||
* @param *string_value
|
* @param *string_value
|
||||||
*
|
*
|
||||||
* @returns the removed event date microseconds
|
* @returns the removed event date microseconds
|
||||||
*/
|
*/
|
||||||
long fsm_remove_log (fsm_log_struct *jj,
|
long fsm_remove_log (struct fsm_log_t *gg_logs,
|
||||||
char *file_source,
|
char *file_source,
|
||||||
char *function_source,
|
char *function_source,
|
||||||
char *string_value)
|
char *string_value)
|
||||||
{
|
{
|
||||||
long usec;
|
// save latest log ref in tmp
|
||||||
fsm_log_unit_struct *tmp = jj->last;
|
struct fsm_log_unit_t *tmp = gg_logs->latest;
|
||||||
if (! tmp) return -1;
|
long usec = tmp->usec;
|
||||||
usec = tmp->usec;
|
|
||||||
jj->last = tmp->prev;
|
// if there is no log, get out
|
||||||
if (jj->last) jj->last->next = NULL;
|
if (! tmp)
|
||||||
else jj->first = NULL;
|
return 0;
|
||||||
free (tmp);
|
|
||||||
|
// remove the log from history
|
||||||
|
gg_logs->latest = tmp->prev;
|
||||||
|
|
||||||
|
// update gg_logs references if needed
|
||||||
|
if (gg_logs->latest) gg_logs->latest->next = NULL;
|
||||||
|
else gg_logs->latest = NULL;
|
||||||
|
|
||||||
|
// free the unit memory
|
||||||
|
fsm_clear_log_unit(tmp);
|
||||||
return usec;
|
return usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,12 +78,12 @@ long fsm_remove_log (fsm_log_struct *jj,
|
||||||
*
|
*
|
||||||
* @since 2024-09
|
* @since 2024-09
|
||||||
*
|
*
|
||||||
* @param *jj
|
* @param *gg_logs
|
||||||
* @returns log length
|
* @returns log length
|
||||||
*/
|
*/
|
||||||
int fsm_get_log_length (fsm_log_struct jj)
|
int fsm_get_log_length (struct fsm_log_t *gg_logs)
|
||||||
{
|
{
|
||||||
fsm_log_unit_struct *a_unit = jj.first;
|
struct fsm_log_unit_t *a_unit = gg_logs->oldest;
|
||||||
int nb = 0;
|
int nb = 0;
|
||||||
while (a_unit)
|
while (a_unit)
|
||||||
{
|
{
|
||||||
|
@ -90,19 +99,19 @@ int fsm_get_log_length (fsm_log_struct jj)
|
||||||
*
|
*
|
||||||
* @since 2024-09
|
* @since 2024-09
|
||||||
*
|
*
|
||||||
* @param *jj
|
* @param *gg_logs
|
||||||
* @param usec
|
* @param usec
|
||||||
* @param *file_source
|
* @param *file_source
|
||||||
* @param *function_source
|
* @param *function_source
|
||||||
* @param *string_value
|
* @param *string_value
|
||||||
*/
|
*/
|
||||||
void fsm_seek_log (fsm_log_struct jj,
|
void fsm_seek_log (struct fsm_log_t *gg_logs,
|
||||||
long usec,
|
long usec,
|
||||||
char *file_source,
|
char *file_source,
|
||||||
char *function_source,
|
char *function_source,
|
||||||
char *string_value)
|
char *string_value)
|
||||||
{
|
{
|
||||||
fsm_log_unit_struct *a_unit = jj.first;
|
struct fsm_log_unit_t *a_unit = gg_logs->oldest;
|
||||||
int nb = 0;
|
int nb = 0;
|
||||||
while (a_unit)
|
while (a_unit)
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
*
|
*
|
||||||
* Limiting the access to gg_logs helps to avoid uncontrolled operations on it.
|
* Limiting the access to gg_logs helps to avoid uncontrolled operations on it.
|
||||||
*/
|
*/
|
||||||
static fsm_log_struct gg_logs;
|
static struct fsm_log_t gg_logs = { 0 };
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,7 +148,7 @@ void fsm_relay_init_log()
|
||||||
*/
|
*/
|
||||||
void fsm_relay_close_log()
|
void fsm_relay_close_log()
|
||||||
{
|
{
|
||||||
fsm_publish_log (gg_logs);
|
fsm_publish_log (&gg_logs);
|
||||||
fsm_clear_log (&gg_logs);
|
fsm_clear_log (&gg_logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
static int string_1_size = 40;
|
static int string_1_size = 40;
|
||||||
static int string_2_size = 40;
|
static int string_2_size = 40;
|
||||||
static int string_3_size = 40;
|
static int string_3_size = 50;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inits the log: a double chained list.
|
* Inits the log: a double chained list.
|
||||||
|
@ -54,12 +54,12 @@ static int string_3_size = 40;
|
||||||
*
|
*
|
||||||
* @since 2024-09
|
* @since 2024-09
|
||||||
*
|
*
|
||||||
* @param *jj
|
* @param *gg_logs
|
||||||
*/
|
*/
|
||||||
void fsm_init_log (fsm_log_struct *jj)
|
void fsm_init_log (struct fsm_log_t *gg_logs)
|
||||||
{
|
{
|
||||||
jj->first = NULL;
|
gg_logs->oldest = NULL;
|
||||||
jj->last = NULL;
|
gg_logs->latest = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,22 +68,38 @@ void fsm_init_log (fsm_log_struct *jj)
|
||||||
*
|
*
|
||||||
* @since 2024-09
|
* @since 2024-09
|
||||||
*
|
*
|
||||||
* @param *jj
|
* @param *gg_logs
|
||||||
*/
|
*/
|
||||||
void fsm_clear_log (fsm_log_struct *jj)
|
void fsm_clear_log (struct fsm_log_t *gg_logs)
|
||||||
{
|
{
|
||||||
fsm_log_unit_struct *tmp;
|
struct fsm_log_unit_t *tmp;
|
||||||
fsm_log_unit_struct *a_unit = jj->first;
|
struct fsm_log_unit_t *a_unit = gg_logs->oldest;
|
||||||
|
|
||||||
while(a_unit)
|
while(a_unit)
|
||||||
{
|
{
|
||||||
tmp = a_unit;
|
tmp = a_unit;
|
||||||
a_unit = a_unit->next;
|
a_unit = a_unit->next;
|
||||||
free (tmp);
|
fsm_clear_log_unit(tmp);
|
||||||
}
|
}
|
||||||
jj->first = NULL;
|
gg_logs->oldest = NULL;
|
||||||
jj->last = NULL;
|
gg_logs->latest = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all the contents of a log unit and takes care
|
||||||
|
* of freeing it.
|
||||||
|
*
|
||||||
|
* @since 2024-11
|
||||||
|
*
|
||||||
|
* @param *unit
|
||||||
|
*/
|
||||||
|
void fsm_clear_log_unit (struct fsm_log_unit_t *unit)
|
||||||
|
{
|
||||||
|
g_free(unit->file_source);
|
||||||
|
g_free(unit->function_source);
|
||||||
|
g_free(unit->string_value);
|
||||||
|
g_free(unit);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a log unit (an event) to the log list.
|
* Adds a log unit (an event) to the log list.
|
||||||
|
@ -94,12 +110,12 @@ void fsm_clear_log (fsm_log_struct *jj)
|
||||||
*
|
*
|
||||||
* @since 2024-09
|
* @since 2024-09
|
||||||
*
|
*
|
||||||
* @param *jj
|
* @param *gg_logs
|
||||||
* @param *file_source
|
* @param *file_source
|
||||||
* @param *function_source
|
* @param *function_source
|
||||||
* @param *string_value
|
* @param *string_value
|
||||||
*/
|
*/
|
||||||
void fsm_add_log_event (fsm_log_struct *jj,
|
void fsm_add_log_event (struct fsm_log_t *gg_logs,
|
||||||
char *file_source,
|
char *file_source,
|
||||||
char *function_source,
|
char *function_source,
|
||||||
char *string_value)
|
char *string_value)
|
||||||
|
@ -107,7 +123,7 @@ void fsm_add_log_event (fsm_log_struct *jj,
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday (&tv, NULL);
|
gettimeofday (&tv, NULL);
|
||||||
|
|
||||||
fsm_log_unit_struct *new_unit = malloc (sizeof(fsm_log_unit_struct));
|
struct fsm_log_unit_t *new_unit = g_malloc0 (sizeof(struct fsm_log_unit_t));
|
||||||
if (! new_unit) exit (EXIT_FAILURE);
|
if (! new_unit) exit (EXIT_FAILURE);
|
||||||
|
|
||||||
new_unit->yy_dd_mm = tv.tv_sec;
|
new_unit->yy_dd_mm = tv.tv_sec;
|
||||||
|
@ -121,13 +137,17 @@ void fsm_add_log_event (fsm_log_struct *jj,
|
||||||
strncpy (new_unit->function_source, function_source, string_2_size - 1);
|
strncpy (new_unit->function_source, function_source, string_2_size - 1);
|
||||||
strncpy (new_unit->string_value, string_value, string_3_size - 1);
|
strncpy (new_unit->string_value, string_value, string_3_size - 1);
|
||||||
|
|
||||||
new_unit->next = jj->first;
|
// first time we log something (don't touch new_unit->prev)
|
||||||
new_unit->prev = NULL;
|
if (gg_logs->oldest == NULL)
|
||||||
|
gg_logs->oldest = new_unit; // record the first reference (once)
|
||||||
|
// not the first time, just update
|
||||||
|
else {
|
||||||
|
new_unit->prev = gg_logs->latest;
|
||||||
|
new_unit->prev->next = new_unit;
|
||||||
|
}
|
||||||
|
|
||||||
if (jj->first) jj->first->prev = new_unit;
|
// in any case, update the latest reference
|
||||||
else jj->last = new_unit;
|
gg_logs->latest = new_unit;
|
||||||
|
|
||||||
jj->first = new_unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,27 +161,43 @@ void fsm_add_log_event (fsm_log_struct *jj,
|
||||||
*
|
*
|
||||||
* @since 2024-09
|
* @since 2024-09
|
||||||
*
|
*
|
||||||
* @param *jj
|
* @param *gg_logs
|
||||||
*/
|
*/
|
||||||
void fsm_publish_log (fsm_log_struct jj)
|
void fsm_publish_log (struct fsm_log_t *gg_logs)
|
||||||
{
|
{
|
||||||
fsm_log_unit_struct *a_unit = jj.last;
|
struct fsm_log_unit_t *a_unit = gg_logs->oldest;
|
||||||
char buf [LOG_MAX_LENGTH];
|
char *timestamp = g_malloc0 (LOG_MAX_LENGTH * sizeof(char));
|
||||||
int nb = 0;
|
int nb = 0;
|
||||||
while (a_unit)
|
while (a_unit)
|
||||||
{
|
{
|
||||||
strftime(buf, sizeof(buf), "%D %T", localtime(&a_unit->yy_dd_mm));
|
strftime(timestamp, LOG_MAX_LENGTH * sizeof(char),
|
||||||
g_message ("%s + %-6ld %6d %-28s %-32s %-40s",
|
"%D %T", localtime(&a_unit->yy_dd_mm));
|
||||||
buf,
|
|
||||||
|
g_message ("%s + %-6ld %6d %-28s %-32s %-45s",
|
||||||
|
timestamp,
|
||||||
a_unit->usec,
|
a_unit->usec,
|
||||||
nb,
|
nb,
|
||||||
a_unit->file_source,
|
a_unit->file_source,
|
||||||
a_unit->function_source,
|
a_unit->function_source,
|
||||||
a_unit->string_value);
|
a_unit->string_value);
|
||||||
free (a_unit->string_value);
|
|
||||||
a_unit = a_unit->prev;
|
a_unit = a_unit->next;
|
||||||
nb ++;
|
nb ++;
|
||||||
}
|
}
|
||||||
|
g_free(timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LEAK SUMMARY:
|
||||||
|
*
|
||||||
|
* g_message (+) or printf
|
||||||
|
* definitely lost: 5,008 bytes in 54 blocks
|
||||||
|
* indirectly lost: 16,151 bytes in 673 blocks
|
||||||
|
*
|
||||||
|
* g_message (-)
|
||||||
|
* definitely lost: 5,776 bytes in 55 blocks
|
||||||
|
* indirectly lost: 17,703 bytes in 728 blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,10 @@ int main (int argc, char **argv)
|
||||||
|
|
||||||
fsm_init ("first instruction / first log");
|
fsm_init ("first instruction / first log");
|
||||||
|
|
||||||
fsm_add_log (INFO, MAIN, "main", "*app = gtk_application_new()",
|
fsm_add_log (INFO, MAIN, "main",
|
||||||
|
"*app = gtk_application_new()",
|
||||||
"| 👉️ trigger app initialization");
|
"| 👉️ trigger app initialization");
|
||||||
|
|
||||||
app = gtk_application_new ("org.gem-graph", G_APPLICATION_DEFAULT_FLAGS);
|
app = gtk_application_new ("org.gem-graph", G_APPLICATION_DEFAULT_FLAGS);
|
||||||
|
|
||||||
fsm_add_log (INFO, MAIN, "main",
|
fsm_add_log (INFO, MAIN, "main",
|
||||||
|
|
Loading…
Reference in New Issue