diff --git a/src/heaptrace.cc b/src/heaptrace.cc index 24f3e1e..71f63bb 100644 --- a/src/heaptrace.cc +++ b/src/heaptrace.cc @@ -26,6 +26,7 @@ enum options { OPT_sort, OPT_flamegraph, OPT_outfile, + OPT_signals, }; static struct argp_option heaptrace_options[] = { @@ -34,6 +35,7 @@ static struct argp_option heaptrace_options[] = { { "sort", 's', "KEYs", 0, "Sort backtraces based on KEYs (size or count)" }, { "flame-graph", OPT_flamegraph, nullptr, 0, "Print heap trace info in flamegraph format" }, { "outfile", OPT_outfile, "FILE", 0, "Save log messages to this file" }, + { "signals", OPT_signals, "KEY:NUM", 0, "Add report signal numbers for given each key" }, { nullptr } }; @@ -62,6 +64,10 @@ static error_t parse_option(int key, char *arg, struct argp_state *state) opts->outfile = arg; break; + case OPT_signals: + opts->signals = arg; + break; + case ARGP_KEY_ARG: if (state->arg_num) return ARGP_ERR_UNKNOWN; @@ -136,6 +142,9 @@ static void setup_child_environ(struct opts *opts, int argc, char *argv[]) if (opts->outfile) setenv("HEAPTRACE_OUTFILE", opts->outfile, 1); + + if (opts->signals) + setenv("HEAPTRACE_SIGNALS", opts->signals, 1); } int main(int argc, char *argv[]) diff --git a/src/heaptrace.h b/src/heaptrace.h index ab60bf0..5011685 100644 --- a/src/heaptrace.h +++ b/src/heaptrace.h @@ -42,6 +42,7 @@ struct opts { const char *sort_keys; bool flamegraph; char *outfile; + char *signals; }; extern opts opts; diff --git a/src/libheaptrace.cc b/src/libheaptrace.cc index d78f1c6..2fffe12 100644 --- a/src/libheaptrace.cc +++ b/src/libheaptrace.cc @@ -6,8 +6,8 @@ #include #include #include - #include + #include #include #include @@ -110,6 +110,35 @@ __constructor static void heaptrace_init() pr_out("[heaptrace] initialized for /proc/%d/maps (%s)\n", pid, comm.c_str()); } + opts.signals = getenv("HEAPTRACE_SIGNALS"); + if (opts.signals) { + auto key_num_vec = utils::string_split(opts.signals, ','); + for (const auto& key_num: key_num_vec) { + auto item_vec = utils::string_split(key_num, ':'); + if (item_vec.size() != 2) { + pr_out("Failed to parsing signals: %s\n", + key_num.c_str()); + break; + } + std::string::size_type sz; + auto signo = std::stoi(item_vec[1], &sz, 10); + if (sz != item_vec[1].size()) { + pr_out("Failed to convert signo %s to number\n", + item_vec[1].c_str()); + break; + } + std::string key = item_vec[0]; + if (key == "size") { + register_sighandler(size_sighandler, signo); + } else if (key == "count") { + register_sighandler(count_sighandler, signo); + } else { + pr_out("Cannot register not supporting key: %s\n", + key.c_str()); + } + } + } + initialized = true; } diff --git a/src/sighandler.cc b/src/sighandler.cc index 2b7ab0c..39b4309 100644 --- a/src/sighandler.cc +++ b/src/sighandler.cc @@ -1,9 +1,8 @@ /* Copyright (c) 2022 LG Electronics Inc. */ /* SPDX-License-Identifier: GPL-2.0 */ -#include - #include "heaptrace.h" #include "stacktrace.h" +#include "sighandler.h" static void sigusr1_handler(int signo) { @@ -23,30 +22,31 @@ static void sigquit_handler(int signo) clear_stackmap(); } -void sighandler_init(void) +void register_sighandler(sighandler_t handler, int signo) { - struct sigaction sigusr1; - struct sigaction sigusr2; - struct sigaction sigquit; - - sigusr1.sa_handler = sigusr1_handler; - sigemptyset(&sigusr1.sa_mask); - sigusr1.sa_flags = 0; + struct sigaction sig; - sigusr2.sa_handler = sigusr2_handler; - sigemptyset(&sigusr2.sa_mask); - sigusr2.sa_flags = 0; + sig.sa_handler = handler; + sigemptyset(&sig.sa_mask); + sig.sa_flags = 0; - sigquit.sa_handler = sigquit_handler; - sigemptyset(&sigquit.sa_mask); - sigquit.sa_flags = 0; + if (sigaction(signo, &sig, nullptr) == -1) + pr_dbg("signal(%d) error", signo); +} - if (sigaction(SIGUSR1, &sigusr1, nullptr) == -1) - pr_dbg("signal(SIGUSR1) error"); +void sighandler_init(void) +{ + register_sighandler(&sigusr1_handler, SIGUSR1); + register_sighandler(&sigusr2_handler, SIGUSR2); + register_sighandler(&sigquit_handler, SIGQUIT); +} - if (sigaction(SIGUSR2, &sigusr2, nullptr) == -1) - pr_dbg("signal(SIGUSR2) error"); +void size_sighandler(int /*unused*/) +{ + dump_stackmap("size", opts.flamegraph); +} - if (sigaction(SIGQUIT, &sigquit, nullptr) == -1) - pr_dbg("signal(SIGQUIT) error"); +void count_sighandler(int /*unused*/) +{ + dump_stackmap("count", opts.flamegraph); } diff --git a/src/sighandler.h b/src/sighandler.h index 5875fdf..12fab4b 100644 --- a/src/sighandler.h +++ b/src/sighandler.h @@ -3,6 +3,11 @@ #ifndef HEAPTOP_SIGHANDLER_H #define HEAPTOP_SIGHANDLER_H +#include + +void register_sighandler(sighandler_t handler, int signo); void sighandler_init(void); +void size_sighandler(int); +void count_sighandler(int); #endif /* HEAPTOP_SIGHANDLER_H */