mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-01 02:52:00 +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_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 */
|
||||
|
58
src/debug.c
58
src/debug.c
@ -68,6 +68,21 @@
|
||||
#define THREAD_DUMP_FSYNC 0x00008000U
|
||||
#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
|
||||
* 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
|
||||
@ -111,6 +126,13 @@ struct post_mortem {
|
||||
/* information about dynamic shared libraries involved */
|
||||
char *libs; // dump of one addr / path per line, or NULL
|
||||
#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) = { };
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int comp;
|
||||
|
||||
#if defined(HA_HAVE_DUMP_LIBS)
|
||||
ha_free(&post_mortem.libs);
|
||||
#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);
|
||||
|
||||
/* 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
|
||||
/* 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
|
||||
|
Loading…
Reference in New Issue
Block a user