mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-07 22:12:08 +00:00
MINOR: debug: add the ability to enter components in the post_mortem struct
Here the idea is to collect components' versions and build options. The main component is haproxy, but the API is made so that any sub-system can easily add a component there (for example the detailed version of a device detection lib, or some info about a lib loaded from Lua). The elements are stored as a pointer to an array of structs and its count so that it's sufficient to issue this in gdb to list them all at once: print *post_mortem.components@post_mortem.nb_components For now we collect name, version, toolchain, toolchain options, build options and path. Maybe more could be useful in the future.
This commit is contained in:
parent
a88a3482b5
commit
6455fd5024
@ -32,4 +32,8 @@ void ha_dump_backtrace(struct buffer *buf, const char *prefix, int dump);
|
|||||||
void ha_backtrace_to_stderr(void);
|
void ha_backtrace_to_stderr(void);
|
||||||
void ha_panic(void);
|
void ha_panic(void);
|
||||||
|
|
||||||
|
void post_mortem_add_component(const char *name, const char *version,
|
||||||
|
const char *toolchain, const char *toolchain_opts,
|
||||||
|
const char *build_settings, const char *path);
|
||||||
|
|
||||||
#endif /* _HAPROXY_DEBUG_H */
|
#endif /* _HAPROXY_DEBUG_H */
|
||||||
|
58
src/debug.c
58
src/debug.c
@ -68,6 +68,21 @@
|
|||||||
#define THREAD_DUMP_FSYNC 0x00008000U
|
#define THREAD_DUMP_FSYNC 0x00008000U
|
||||||
#define THREAD_DUMP_PMASK 0x7FFF0000U
|
#define THREAD_DUMP_PMASK 0x7FFF0000U
|
||||||
|
|
||||||
|
/* Description of a component with name, version, path, build options etc. E.g.
|
||||||
|
* one of them is haproxy. Others might be some clearly identified shared libs.
|
||||||
|
* They're intentionally self-contained and to be placed into an array to make
|
||||||
|
* it easier to find them in a core. The important fields (name and version)
|
||||||
|
* are locally allocated, other ones are dynamic.
|
||||||
|
*/
|
||||||
|
struct post_mortem_component {
|
||||||
|
char name[32]; // symbolic short name
|
||||||
|
char version[32]; // exact version
|
||||||
|
char *toolchain; // compiler and version (e.g. gcc-11.4.0)
|
||||||
|
char *toolchain_opts; // optims, arch-specific options (e.g. CFLAGS)
|
||||||
|
char *build_settings; // build options (e.g. USE_*, TARGET, etc)
|
||||||
|
char *path; // path if known.
|
||||||
|
};
|
||||||
|
|
||||||
/* This is a collection of information that are centralized to help with core
|
/* This is a collection of information that are centralized to help with core
|
||||||
* dump analysis. It must be used with a public variable and gather elements
|
* dump analysis. It must be used with a public variable and gather elements
|
||||||
* as much as possible without dereferences so that even when identified in a
|
* as much as possible without dereferences so that even when identified in a
|
||||||
@ -111,6 +126,13 @@ struct post_mortem {
|
|||||||
/* information about dynamic shared libraries involved */
|
/* information about dynamic shared libraries involved */
|
||||||
char *libs; // dump of one addr / path per line, or NULL
|
char *libs; // dump of one addr / path per line, or NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* info about identified distinct components (executable, shared libs, etc).
|
||||||
|
* These can be all listed at once in gdb using:
|
||||||
|
* p *post_mortem.components@post_mortem.nb_components
|
||||||
|
*/
|
||||||
|
uint nb_components; // # of components below
|
||||||
|
struct post_mortem_component *components; // NULL or array
|
||||||
} post_mortem ALIGNED(256) = { };
|
} post_mortem ALIGNED(256) = { };
|
||||||
|
|
||||||
/* Points to a copy of the buffer where the dump functions should write, when
|
/* Points to a copy of the buffer where the dump functions should write, when
|
||||||
@ -2165,13 +2187,49 @@ REGISTER_POST_CHECK(feed_post_mortem);
|
|||||||
|
|
||||||
static void deinit_post_mortem(void)
|
static void deinit_post_mortem(void)
|
||||||
{
|
{
|
||||||
|
int comp;
|
||||||
|
|
||||||
#if defined(HA_HAVE_DUMP_LIBS)
|
#if defined(HA_HAVE_DUMP_LIBS)
|
||||||
ha_free(&post_mortem.libs);
|
ha_free(&post_mortem.libs);
|
||||||
#endif
|
#endif
|
||||||
|
for (comp = 0; comp < post_mortem.nb_components; comp++) {
|
||||||
|
free(post_mortem.components[comp].toolchain);
|
||||||
|
free(post_mortem.components[comp].toolchain_opts);
|
||||||
|
free(post_mortem.components[comp].build_settings);
|
||||||
|
free(post_mortem.components[comp].path);
|
||||||
|
}
|
||||||
|
ha_free(&post_mortem.components);
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_POST_DEINIT(deinit_post_mortem);
|
REGISTER_POST_DEINIT(deinit_post_mortem);
|
||||||
|
|
||||||
|
/* Appends a component to the list of post_portem info. May silently fail
|
||||||
|
* on allocation errors but we don't care since the goal is to provide info
|
||||||
|
* we have in case it helps.
|
||||||
|
*/
|
||||||
|
void post_mortem_add_component(const char *name, const char *version,
|
||||||
|
const char *toolchain, const char *toolchain_opts,
|
||||||
|
const char *build_settings, const char *path)
|
||||||
|
{
|
||||||
|
struct post_mortem_component *comp;
|
||||||
|
int nbcomp = post_mortem.nb_components;
|
||||||
|
|
||||||
|
comp = realloc(post_mortem.components, (nbcomp + 1) * sizeof(*comp));
|
||||||
|
if (!comp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(&comp[nbcomp], 0, sizeof(*comp));
|
||||||
|
strlcpy2(comp[nbcomp].name, name, sizeof(comp[nbcomp].name));
|
||||||
|
strlcpy2(comp[nbcomp].version, version, sizeof(comp[nbcomp].version));
|
||||||
|
comp[nbcomp].toolchain = strdup(toolchain);
|
||||||
|
comp[nbcomp].toolchain_opts = strdup(toolchain_opts);
|
||||||
|
comp[nbcomp].build_settings = strdup(build_settings);
|
||||||
|
comp[nbcomp].path = strdup(path);
|
||||||
|
|
||||||
|
post_mortem.nb_components++;
|
||||||
|
post_mortem.components = comp;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_THREAD
|
#ifdef USE_THREAD
|
||||||
/* init code is called one at a time so let's collect all per-thread info on
|
/* init code is called one at a time so let's collect all per-thread info on
|
||||||
* the last starting thread. These info are not critical anyway and there's no
|
* the last starting thread. These info are not critical anyway and there's no
|
||||||
|
Loading…
Reference in New Issue
Block a user