Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/heaptrace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum options {
OPT_sort,
OPT_flamegraph,
OPT_outfile,
OPT_signals,
};

static struct argp_option heaptrace_options[] = {
Expand All @@ -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 }
};

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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[])
Expand Down
1 change: 1 addition & 0 deletions src/heaptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct opts {
const char *sort_keys;
bool flamegraph;
char *outfile;
char *signals;
};

extern opts opts;
Expand Down
31 changes: 30 additions & 1 deletion src/libheaptrace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <csignal>

#include <dlfcn.h>
#include <sys/mman.h>
#include <unistd.h>
Expand Down Expand Up @@ -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",

Copilot AI Jun 22, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message "Failed to parsing signals" is grammatically incorrect; consider "Failed to parse signal definition: %s".

Suggested change
pr_out("Failed to parsing signals: %s\n",
pr_out("Failed to parse signals: %s\n",

Copilot uses AI. Check for mistakes.
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",

Copilot AI Jun 22, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error text is awkward; consider "Unsupported key: %s" for clarity.

Suggested change
pr_out("Cannot register not supporting key: %s\n",
pr_out("Unsupported key: %s\n",

Copilot uses AI. Check for mistakes.
key.c_str());
}
}
}

initialized = true;
}

Expand Down
44 changes: 22 additions & 22 deletions src/sighandler.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/* Copyright (c) 2022 LG Electronics Inc. */
/* SPDX-License-Identifier: GPL-2.0 */
#include <csignal>

#include "heaptrace.h"
#include "stacktrace.h"
#include "sighandler.h"

static void sigusr1_handler(int signo)
{
Expand All @@ -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);
}
5 changes: 5 additions & 0 deletions src/sighandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
#ifndef HEAPTOP_SIGHANDLER_H
#define HEAPTOP_SIGHANDLER_H

#include <csignal>

void register_sighandler(sighandler_t handler, int signo);
void sighandler_init(void);
void size_sighandler(int);
void count_sighandler(int);

#endif /* HEAPTOP_SIGHANDLER_H */