[DTrace-devel] [PATCH 07/13] Set interrupt signal handler earlier
Kris Van Hees
kris.van.hees at oracle.com
Mon Jul 6 21:57:10 PDT 2020
On Wed, Jul 01, 2020 at 10:41:12PM -0400, eugene.loh at oracle.com wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
>
> We were creating probes and attaching BPF programs to them before
> setting the interrupt signal handler. That meant that there was a
> window during which an interrupt signal would kill dtrace without
> probe cleanup taking place, polluting /sys/kernel/debug/tracing with
> custom DTrace uprobes and kprobes.
>
> Set the interrupt signal handler before probes are attached and BPF
> programs created. One can test g_intr==0 more liberally to bypass
> operations and move to dt_close() more quickly.
>
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
> ---
> cmd/dtrace.c | 26 +++++++++++++-------------
> 1 file changed, 13 insertions(+), 13 deletions(-)
>
> diff --git a/cmd/dtrace.c b/cmd/dtrace.c
> index cef86ef2..868cd3b9 100644
> --- a/cmd/dtrace.c
> +++ b/cmd/dtrace.c
> @@ -1373,10 +1373,18 @@ main(int argc, char *argv[])
> if (g_ofile != NULL && (g_ofp = fopen(g_ofile, "a")) == NULL)
> fatal("failed to open output file '%s'", g_ofile);
>
> + (void) sigemptyset(&act.sa_mask);
Drop the (void).
> + act.sa_flags = 0;
> + act.sa_handler = intr;
> + if (sigaction(SIGINT, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
> + (void) sigaction(SIGINT, &act, NULL);
Drop the (void).
> + if (sigaction(SIGTERM, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
> + (void) sigaction(SIGTERM, &act, NULL);
Drop the (void).
> +
> for (i = 0; i < g_cmdc; i++)
> exec_prog(&g_cmdv[i]);
>
> - if (done) {
> + if (done || g_intr) {
> dtrace_close(g_dtp);
> return (g_status);
> }
> @@ -1480,7 +1488,8 @@ main(int argc, char *argv[])
> /*
> * Start tracing.
> */
> - go();
> + if (g_intr == 0)
> + go();
I think the following would be more clear (to retain the overall normal flow
of statements when Ctrl-C is not issued):
if (g_intr) {
dtrace_close(g_dtp);
return g_status;
}
or alternatively, you could use:
if (g_intr)
goto out;
> (void) dtrace_getopt(g_dtp, "flowindent", &opt);
> g_flowindent = opt != DTRACEOPT_UNSET;
> @@ -1492,23 +1501,14 @@ main(int argc, char *argv[])
> if (opt != DTRACEOPT_UNSET)
> notice("allowing destructive actions\n");
>
> - (void) sigemptyset(&act.sa_mask);
> - act.sa_flags = 0;
> - act.sa_handler = intr;
> -
> - if (sigaction(SIGINT, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
> - (void) sigaction(SIGINT, &act, NULL);
> -
> - if (sigaction(SIGTERM, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
> - (void) sigaction(SIGTERM, &act, NULL);
> -
> /*
> * Now that tracing is active and we are ready to consume trace data,
> * continue any grabbed or created processes, setting them running
> * using the /proc control mechanism inside of libdtrace.
> */
> for (i = 0; i < g_psc; i++)
> - dtrace_proc_continue(g_dtp, g_psv[i]);
> + if (g_intr == 0)
> + dtrace_proc_continue(g_dtp, g_psv[i]);
Put curly brackets around the body of the loop because that tends to be more
clear. I am also not 100% certain it is safe to potentially interrupt the
resuming of user processes here and yet still apply dtrace_proc_release to all
of processes (even those that were not resumed) before we do dtrace_close().
I would use if (g_intr) goto release_procs; anhd set a label release_procs
before the loop to do dtrace_proc_release. Again, this highlghts that code
path as the exception case.
> g_pslive = g_psc; /* count for prochandler() */
>
> --
> 2.18.2
>
>
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel
More information about the DTrace-devel
mailing list