[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251006115555-9822f5f1-fc9d-4d6a-9735-274b242e0eba@linutronix.de>
Date: Mon, 6 Oct 2025 12:10:49 +0200
From: Thomas Weißschuh <thomas.weissschuh@...utronix.de>
To: Gabriele Monaco <gmonaco@...hat.com>
Cc: Nam Cao <namcao@...utronix.de>, linux-kernel@...r.kernel.org,
linux-trace-kernel@...r.kernel.org, Steven Rostedt <rostedt@...dmis.org>,
Masami Hiramatsu <mhiramat@...nel.org>, Mathieu Desnoyers <mathieu.desnoyers@...icios.com>
Subject: Re: [PATCH] rv: Add signal reactor
Hi Gabriele,
On Fri, Oct 03, 2025 at 08:30:10AM +0200, Gabriele Monaco wrote:
> 2025-10-02T14:56:23Z Nam Cao <namcao@...utronix.de>:
>
> > Thomas Weißschuh <thomas.weissschuh@...utronix.de> writes:
> >> I am wondering if it would make sense to add a new tracepoint that
> >> fires in addition of the reactors. That would allow multiple
> >> simultaneous consumers and also bespoke handlers in userspace.
> >
> > We do have tracepoints for each monitor in: kernel/trace/rv/rv_trace.h
> >
> > And yeah, I think it is a nice idea for all the consumers to use these
> > tracepoints intead (that includes rtapp testing, and also the existing
> > reactors). It would simplify things, as the monitors do not have to
> > worry about the reactors, they only need to invoke tracepoints.
> >
> > But this also makes me think about the necessity of the existing
> > reactors. What do they offer that tracepoints do not? Myself I almost
> > never use the reactors, so I'm thinking about removing them. But maybe
> > @Gabriele has objections?
>
> Well, many use cases might be better off with tracepoints, but reactors do
> things tracepoints cannot really do.
> Printk is much faster (and perhaps more reliable) than the trace buffer for
> printing, panic can be used to gather a kernel dump.
> One may just attach to tracepoints via libtracefs/BPF and do most of the things
> you'd want to do with a new reactor, but I see reactors much easier to use from
> scripts, for instance.
>
> LTLs don't benefit as much as they don't print any additional information via
> reactors, but DA/HA give hints on what's wrong.
>
> I wouldn't get rid of reactors until they become a huge maintenance burden, but
> probably we could think about it twice before extending or making them more
> complex.
The existing reactors could be implemented on top of the tracepoints.
This should make the RV core a bit simpler.
Note: The current interface between the RV core and the reactors is inflexible.
Passing only opaque varargs requires all reactors to format the string from
within the tracepoint handler, as they can not know how long the objects
referenced by the varargs are valid. Passing the actual objects would allow
for example the signal reactor to format its message as part of the task_work
handler instead of the signal handler and avoid the allocation of a fixed size
message buffer.
> For instance, what's the exact use case of the signal reactor? Isn't it simpler
> to do everything in BPF? Is the signal needed at all or something else (e.g.
> perf) would do the job?
The signal reactor is convenient to write automated tests. It can be used to
validate the monitors by triggering known-bad systemcalls from a test
executable and expect it to be killed with the reactor signal, see below for
an example.
On the other hand it can be used to validate that the kernel itself does not
regress with respect to RV-validated properties. For example the test program
can enable the rtapp monitor and run an example RT application using all kinds
of known-good IPC mechanisms without it being killed.
Thomas
Example selftest to make sure rtapp/sleep monitors detect the invalid
clock_nanosleep(CLOCK_REALTIME). I use this to also test my reactor:
#include "kselftest.h"
#include "test_utils.h" /* Provides
#include <sched.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
static void test_nanosleep(void)
{
struct timespec sleep_time;
pid_t pid;
int ret;
pid = fork();
switch (pid) {
case -1:
ksft_test_result_fail("%s: failed to fork: %s\n", __func__, strerror(errno));
return;
case 0:
sleep_time.tv_sec = 2;
sleep_time.tv_nsec = 0;
ret = clock_nanosleep(CLOCK_REALTIME, 0, &sleep_time, NULL);
_exit(ret != 0);
default:
waitpid(pid, &ret, 0);
ksft_print_msg("ret 0x%x\n", ret);
}
ksft_test_result(ret == 0, "%s\n", __func__);
}
static void become_realtime(void)
{
struct sched_param p = {
.sched_priority = 1,
};
int ret;
ret = sched_setscheduler(0, SCHED_FIFO, &p);
if (ret == -1) {
ksft_print_header();
ksft_set_plan(1);
ksft_test_result_fail("Failed to become realtime: %s\n", strerror(errno));
ksft_finished();
}
}
int main(void)
{
int ret;
become_realtime();
ret = rtapp_enable();
if (ret) {
ksft_print_header();
ksft_set_plan(1);
ksft_test_result_fail("Failed to enable rtapp: %s\n", strerror(errno));
ksft_finished();
}
ksft_print_header();
ksft_set_plan(1);
test_nanosleep();
rtapp_disable();
ksft_finished();
}
Powered by blists - more mailing lists