Skip to content

Commit

Permalink
API: Allow sending a SIGUSR1 signal for requesting reports on demand
Browse files Browse the repository at this point in the history
The tool currently only produces reports on a clean exit from the
analyzed program, which is not always achievable (daemons, programs
crashing, etc.), and also using `hu_report()` as an API, which might
also not be doable in all scenarios (e.g. no source code for the
analyzed program). An "on demand" report requested from "the outside
world" has proven very useful in some debugging scenarios.

Having a signal that could be sent to the analyzed program (e.g. sent
from a shell) and have the `heapusage` tool catch it and produce a
report in response is very helpful.

This way, install a signal handler for the `SIGUSR1` and `SIGUSR2` user
defined signals and, for `SIGUSR1` trigger a report using
`log_summary_safe()`, just like the `hu_report()` API does. Leave the
`SIGUSR2` available for other future requests.

Update `README.md` with this new usage possibility.

Signed-off-by: Ricardo Silva <[email protected]>
  • Loading branch information
rjpdasilva committed May 24, 2024
1 parent 3d60e08 commit 2de0126
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ function. For doing so, they must include the `huapi.h` public header file, link
with the Heapusage shared library itself and call `hu_report()` when wanted.
Still, this only works if the program is running through the `heapusage` tool.

Alternatively, on Linux, sending a `SIGUSR1` signal to the program being run
through Heapusage will also produce a Heapusage report on demand.

For both `hu_report()` and `SIGUSR1`, it should be noted that the report will
reflect the state when they are used, which can e.g. report non-freed memory
that might be still released before the program exits and, therefore, not
necessarily constitute a memory leak.

Output Format
=============
Example output:
Expand Down
30 changes: 30 additions & 0 deletions src/humain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,34 @@ static inline bool hu_get_env_bool(const char* name)
return (strcmp(value, "1") == 0);
}

#if defined(__linux__)
static void hu_sigusr_handler(int sig)
{
switch (sig) {
case SIGUSR1:
log_message("Caught User Signal: SIGUSR1 (%d): Request Log Summary\n", sig);
log_summary_safe();
break;
default:
log_message("Caught User Signal: Unexpected Signal (%d): Ignore\n", sig);
break;
}
}
#endif

static void hu_sigusr_init(void)
{
#if defined(__linux__)
struct sigaction sa;

sa.sa_handler = hu_sigusr_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGUSR2, &sa, NULL);
#endif
}


/* ----------- Global Functions ---------------------------------- */
extern "C"
Expand All @@ -116,6 +144,8 @@ void __attribute__ ((constructor)) hu_init(void)
hu_malloc_init(hu_overflow, hu_useafterfree, hu_minsize);
}

hu_sigusr_init();

/* Do not enable preload for child processes */
unsetenv("DYLD_INSERT_LIBRARIES");
unsetenv("LD_PRELOAD");
Expand Down

0 comments on commit 2de0126

Please sign in to comment.