]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rtla: Exit on memory allocation failures during initialization
authorWander Lairson Costa <wander@redhat.com>
Mon, 9 Mar 2026 19:46:14 +0000 (16:46 -0300)
committerTomas Glozar <tglozar@redhat.com>
Tue, 10 Mar 2026 09:32:37 +0000 (10:32 +0100)
Most memory allocations in rtla happen during early initialization
before any resources are acquired that would require cleanup. In these
cases, propagating allocation errors just adds complexity without any
benefit. There's nothing to clean up, and the program must exit anyway.

This patch introduces fatal allocation wrappers (calloc_fatal,
reallocarray_fatal, strdup_fatal) that call fatal() on allocation
failure. These wrappers simplify the code by eliminating unnecessary
error propagation paths.

The patch converts early allocations to use these wrappers in
actions_init() and related action functions, osnoise_context_alloc()
and osnoise_init_tool(), trace_instance_init() and trace event
functions, and parameter structure allocations in main functions.

This simplifies the code while maintaining the same behavior: immediate
exit on allocation failure during initialization. Allocations that
require cleanup, such as those in histogram allocation functions with
goto cleanup paths, are left unchanged and continue to return errors.

Signed-off-by: Wander Lairson Costa <wander@redhat.com>
Link: https://lore.kernel.org/r/20260309195040.1019085-2-wander@redhat.com
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
tools/tracing/rtla/src/actions.c
tools/tracing/rtla/src/actions.h
tools/tracing/rtla/src/osnoise.c
tools/tracing/rtla/src/osnoise_hist.c
tools/tracing/rtla/src/osnoise_top.c
tools/tracing/rtla/src/timerlat_hist.c
tools/tracing/rtla/src/timerlat_top.c
tools/tracing/rtla/src/trace.c
tools/tracing/rtla/src/trace.h
tools/tracing/rtla/src/utils.c
tools/tracing/rtla/src/utils.h

index a42615011962de35ed68951b7f669d1f31198a7d..22b8283a183f353ec70b3e0f75983bc82b625dd6 100644 (file)
@@ -15,7 +15,7 @@ void
 actions_init(struct actions *self)
 {
        self->size = action_default_size;
-       self->list = calloc(self->size, sizeof(struct action));
+       self->list = calloc_fatal(self->size, sizeof(struct action));
        self->len = 0;
        self->continue_flag = false;
 
@@ -50,8 +50,10 @@ static struct action *
 actions_new(struct actions *self)
 {
        if (self->len >= self->size) {
-               self->size *= 2;
-               self->list = realloc(self->list, self->size * sizeof(struct action));
+               const size_t new_size = self->size * 2;
+
+               self->list = reallocarray_fatal(self->list, new_size, sizeof(struct action));
+               self->size = new_size;
        }
 
        return &self->list[self->len++];
@@ -60,25 +62,21 @@ actions_new(struct actions *self)
 /*
  * actions_add_trace_output - add an action to output trace
  */
-int
+void
 actions_add_trace_output(struct actions *self, const char *trace_output)
 {
        struct action *action = actions_new(self);
 
        self->present[ACTION_TRACE_OUTPUT] = true;
        action->type = ACTION_TRACE_OUTPUT;
-       action->trace_output = calloc(strlen(trace_output) + 1, sizeof(char));
-       if (!action->trace_output)
-               return -1;
+       action->trace_output = calloc_fatal(strlen(trace_output) + 1, sizeof(char));
        strcpy(action->trace_output, trace_output);
-
-       return 0;
 }
 
 /*
  * actions_add_trace_output - add an action to send signal to a process
  */
-int
+void
 actions_add_signal(struct actions *self, int signal, int pid)
 {
        struct action *action = actions_new(self);
@@ -87,40 +85,32 @@ actions_add_signal(struct actions *self, int signal, int pid)
        action->type = ACTION_SIGNAL;
        action->signal = signal;
        action->pid = pid;
-
-       return 0;
 }
 
 /*
  * actions_add_shell - add an action to execute a shell command
  */
-int
+void
 actions_add_shell(struct actions *self, const char *command)
 {
        struct action *action = actions_new(self);
 
        self->present[ACTION_SHELL] = true;
        action->type = ACTION_SHELL;
-       action->command = calloc(strlen(command) + 1, sizeof(char));
-       if (!action->command)
-               return -1;
+       action->command = calloc_fatal(strlen(command) + 1, sizeof(char));
        strcpy(action->command, command);
-
-       return 0;
 }
 
 /*
  * actions_add_continue - add an action to resume measurement
  */
-int
+void
 actions_add_continue(struct actions *self)
 {
        struct action *action = actions_new(self);
 
        self->present[ACTION_CONTINUE] = true;
        action->type = ACTION_CONTINUE;
-
-       return 0;
 }
 
 /*
@@ -176,7 +166,8 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
                                /* Only one argument allowed */
                                return -1;
                }
-               return actions_add_trace_output(self, trace_output);
+               actions_add_trace_output(self, trace_output);
+               break;
        case ACTION_SIGNAL:
                /* Takes two arguments, num (signal) and pid */
                while (token != NULL) {
@@ -200,21 +191,26 @@ actions_parse(struct actions *self, const char *trigger, const char *tracefn)
                        /* Missing argument */
                        return -1;
 
-               return actions_add_signal(self, signal, pid);
+               actions_add_signal(self, signal, pid);
+               break;
        case ACTION_SHELL:
                if (token == NULL)
                        return -1;
-               if (strlen(token) > 8 && strncmp(token, "command=", 8) == 0)
-                       return actions_add_shell(self, token + 8);
-               return -1;
+               if (strlen(token) > 8 && strncmp(token, "command=", 8))
+                       return -1;
+               actions_add_shell(self, token + 8);
+               break;
        case ACTION_CONTINUE:
                /* Takes no argument */
                if (token != NULL)
                        return -1;
-               return actions_add_continue(self);
+               actions_add_continue(self);
+               break;
        default:
                return -1;
        }
+
+       return 0;
 }
 
 /*
index fb77069c972baee3b0e48b29fdd37e1bbcf4c50f..034048682fefbafbcdee9fa1e671cd35430b5ab1 100644 (file)
@@ -49,9 +49,9 @@ struct actions {
 
 void actions_init(struct actions *self);
 void actions_destroy(struct actions *self);
-int actions_add_trace_output(struct actions *self, const char *trace_output);
-int actions_add_signal(struct actions *self, int signal, int pid);
-int actions_add_shell(struct actions *self, const char *command);
-int actions_add_continue(struct actions *self);
+void actions_add_trace_output(struct actions *self, const char *trace_output);
+void actions_add_signal(struct actions *self, int signal, int pid);
+void actions_add_shell(struct actions *self, const char *command);
+void actions_add_continue(struct actions *self);
 int actions_parse(struct actions *self, const char *trigger, const char *tracefn);
 int actions_perform(struct actions *self);
index 945eb61efc46567079b69f75fb2724bc388a827f..ec074cd53dd8447b7d35d6abd5d41c22a50c5e0d 100644 (file)
@@ -938,9 +938,7 @@ struct osnoise_context *osnoise_context_alloc(void)
 {
        struct osnoise_context *context;
 
-       context = calloc(1, sizeof(*context));
-       if (!context)
-               return NULL;
+       context = calloc_fatal(1, sizeof(*context));
 
        context->orig_stop_us           = OSNOISE_OPTION_INIT_VAL;
        context->stop_us                = OSNOISE_OPTION_INIT_VAL;
@@ -1017,24 +1015,16 @@ void osnoise_destroy_tool(struct osnoise_tool *top)
 struct osnoise_tool *osnoise_init_tool(char *tool_name)
 {
        struct osnoise_tool *top;
-       int retval;
-
-       top = calloc(1, sizeof(*top));
-       if (!top)
-               return NULL;
 
+       top = calloc_fatal(1, sizeof(*top));
        top->context = osnoise_context_alloc();
-       if (!top->context)
-               goto out_err;
 
-       retval = trace_instance_init(&top->trace, tool_name);
-       if (retval)
-               goto out_err;
+       if (trace_instance_init(&top->trace, tool_name)) {
+               osnoise_destroy_tool(top);
+               return NULL;
+       }
 
        return top;
-out_err:
-       osnoise_destroy_tool(top);
-       return NULL;
 }
 
 /*
index 4181e025511a8f1622294a3322fb146da405aae8..8ad816b80265d968203d64f0b125b41bfdae5db7 100644 (file)
@@ -463,9 +463,7 @@ static struct common_params
        int c;
        char *trace_output = NULL;
 
-       params = calloc(1, sizeof(*params));
-       if (!params)
-               exit(1);
+       params = calloc_fatal(1, sizeof(*params));
 
        actions_init(&params->common.threshold_actions);
        actions_init(&params->common.end_actions);
@@ -575,22 +573,16 @@ static struct common_params
                        params->common.hist.with_zeros = 1;
                        break;
                case '4': /* trigger */
-                       if (params->common.events) {
-                               retval = trace_event_add_trigger(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding trigger %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_trigger(params->common.events, optarg);
+                       else
                                fatal("--trigger requires a previous -e");
-                       }
                        break;
                case '5': /* filter */
-                       if (params->common.events) {
-                               retval = trace_event_add_filter(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding filter %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_filter(params->common.events, optarg);
+                       else
                                fatal("--filter requires a previous -e");
-                       }
                        break;
                case '6':
                        params->common.warmup = get_llong_from_str(optarg);
index f92caea9f2e90fc99dcdd996688881d0f6048675..244bdce022ad3e5fa8e73776952248f38ea28380 100644 (file)
@@ -312,9 +312,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
        int c;
        char *trace_output = NULL;
 
-       params = calloc(1, sizeof(*params));
-       if (!params)
-               exit(1);
+       params = calloc_fatal(1, sizeof(*params));
 
        actions_init(&params->common.threshold_actions);
        actions_init(&params->common.end_actions);
@@ -402,22 +400,16 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
                        params->threshold = get_llong_from_str(optarg);
                        break;
                case '0': /* trigger */
-                       if (params->common.events) {
-                               retval = trace_event_add_trigger(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding trigger %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_trigger(params->common.events, optarg);
+                       else
                                fatal("--trigger requires a previous -e");
-                       }
                        break;
                case '1': /* filter */
-                       if (params->common.events) {
-                               retval = trace_event_add_filter(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding filter %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_filter(params->common.events, optarg);
+                       else
                                fatal("--filter requires a previous -e");
-                       }
                        break;
                case '2':
                        params->common.warmup = get_llong_from_str(optarg);
index ee1af251c94dc18d9aa566f2ccda357ea4236e24..6524be4e2bf794c49f3c3be37bba42fe306f5f26 100644 (file)
@@ -760,9 +760,7 @@ static struct common_params
        int c;
        char *trace_output = NULL;
 
-       params = calloc(1, sizeof(*params));
-       if (!params)
-               exit(1);
+       params = calloc_fatal(1, sizeof(*params));
 
        actions_init(&params->common.threshold_actions);
        actions_init(&params->common.end_actions);
@@ -911,22 +909,16 @@ static struct common_params
                        params->common.hist.with_zeros = 1;
                        break;
                case '6': /* trigger */
-                       if (params->common.events) {
-                               retval = trace_event_add_trigger(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding trigger %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_trigger(params->common.events, optarg);
+                       else
                                fatal("--trigger requires a previous -e");
-                       }
                        break;
                case '7': /* filter */
-                       if (params->common.events) {
-                               retval = trace_event_add_filter(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding filter %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_filter(params->common.events, optarg);
+                       else
                                fatal("--filter requires a previous -e");
-                       }
                        break;
                case '8':
                        params->dma_latency = get_llong_from_str(optarg);
index cc296c9d7fe7323f09edb1a7bec0e97978baa637..8dd04c5ffb686c47e39f5a0d063b0dbed2d4daa5 100644 (file)
@@ -526,9 +526,7 @@ static struct common_params
        int c;
        char *trace_output = NULL;
 
-       params = calloc(1, sizeof(*params));
-       if (!params)
-               exit(1);
+       params = calloc_fatal(1, sizeof(*params));
 
        actions_init(&params->common.threshold_actions);
        actions_init(&params->common.end_actions);
@@ -656,22 +654,16 @@ static struct common_params
                        params->common.user_data = true;
                        break;
                case '0': /* trigger */
-                       if (params->common.events) {
-                               retval = trace_event_add_trigger(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding trigger %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_trigger(params->common.events, optarg);
+                       else
                                fatal("--trigger requires a previous -e");
-                       }
                        break;
                case '1': /* filter */
-                       if (params->common.events) {
-                               retval = trace_event_add_filter(params->common.events, optarg);
-                               if (retval)
-                                       fatal("Error adding filter %s", optarg);
-                       } else {
+                       if (params->common.events)
+                               trace_event_add_filter(params->common.events, optarg);
+                       else
                                fatal("--filter requires a previous -e");
-                       }
                        break;
                case '2': /* dma-latency */
                        params->dma_latency = get_llong_from_str(optarg);
index b8be3e28680eea54473f5bb2391cc473e86f12ac..211ca54b15b0e4cf2b6e225ece8d93ec8362a61a 100644 (file)
@@ -191,9 +191,7 @@ void trace_instance_destroy(struct trace_instance *trace)
  */
 int trace_instance_init(struct trace_instance *trace, char *tool_name)
 {
-       trace->seq = calloc(1, sizeof(*trace->seq));
-       if (!trace->seq)
-               goto out_err;
+       trace->seq = calloc_fatal(1, sizeof(*trace->seq));
 
        trace_seq_init(trace->seq);
 
@@ -274,15 +272,9 @@ struct trace_events *trace_event_alloc(const char *event_string)
 {
        struct trace_events *tevent;
 
-       tevent = calloc(1, sizeof(*tevent));
-       if (!tevent)
-               return NULL;
+       tevent = calloc_fatal(1, sizeof(*tevent));
 
-       tevent->system = strdup(event_string);
-       if (!tevent->system) {
-               free(tevent);
-               return NULL;
-       }
+       tevent->system = strdup_fatal(event_string);
 
        tevent->event = strstr(tevent->system, ":");
        if (tevent->event) {
@@ -296,31 +288,23 @@ struct trace_events *trace_event_alloc(const char *event_string)
 /*
  * trace_event_add_filter - record an event filter
  */
-int trace_event_add_filter(struct trace_events *event, char *filter)
+void trace_event_add_filter(struct trace_events *event, char *filter)
 {
        if (event->filter)
                free(event->filter);
 
-       event->filter = strdup(filter);
-       if (!event->filter)
-               return 1;
-
-       return 0;
+       event->filter = strdup_fatal(filter);
 }
 
 /*
  * trace_event_add_trigger - record an event trigger action
  */
-int trace_event_add_trigger(struct trace_events *event, char *trigger)
+void trace_event_add_trigger(struct trace_events *event, char *trigger)
 {
        if (event->trigger)
                free(event->trigger);
 
-       event->trigger = strdup(trigger);
-       if (!event->trigger)
-               return 1;
-
-       return 0;
+       event->trigger = strdup_fatal(trigger);
 }
 
 /*
index 1e5aee4b828ddd620a01d7eb41c0b1e040b571a9..95b911a2228b2c1a8583795a9941f8af68cc23ec 100644 (file)
@@ -45,6 +45,6 @@ void trace_events_destroy(struct trace_instance *instance,
 int trace_events_enable(struct trace_instance *instance,
                          struct trace_events *events);
 
-int trace_event_add_filter(struct trace_events *event, char *filter);
-int trace_event_add_trigger(struct trace_events *event, char *trigger);
+void trace_event_add_filter(struct trace_events *event, char *filter);
+void trace_event_add_trigger(struct trace_events *event, char *trigger);
 int trace_set_buffer_size(struct trace_instance *trace, int size);
index 77593718766a6c91a760918a89de0b6b5785b4fd..7da1913c5c02e7e577896e545f12a1ec670d8ca2 100644 (file)
@@ -1040,3 +1040,38 @@ int strtoi(const char *s, int *res)
        *res = (int) lres;
        return 0;
 }
+
+static inline void fatal_alloc(void)
+{
+       fatal("Error allocating memory\n");
+}
+
+void *calloc_fatal(size_t n, size_t size)
+{
+       void *p = calloc(n, size);
+
+       if (!p)
+               fatal_alloc();
+
+       return p;
+}
+
+void *reallocarray_fatal(void *p, size_t n, size_t size)
+{
+       p = reallocarray(p, n, size);
+
+       if (!p)
+               fatal_alloc();
+
+       return p;
+}
+
+char *strdup_fatal(const char *s)
+{
+       char *p = strdup(s);
+
+       if (!p)
+               fatal_alloc();
+
+       return p;
+}
index 80d5ec0cf93488c20e8ec3f9d257238585536338..163b4ec37d3552623907ec55df6357da6d69184e 100644 (file)
@@ -76,6 +76,9 @@ int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr);
 int set_comm_cgroup(const char *comm_prefix, const char *cgroup);
 int set_pid_cgroup(pid_t pid, const char *cgroup);
 int set_cpu_dma_latency(int32_t latency);
+void *calloc_fatal(size_t n, size_t size);
+void *reallocarray_fatal(void *p, size_t n, size_t size);
+char *strdup_fatal(const char *s);
 #ifdef HAVE_LIBCPUPOWER_SUPPORT
 int save_cpu_idle_disable_state(unsigned int cpu);
 int restore_cpu_idle_disable_state(unsigned int cpu);