Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf trace: Avoid early exit due SIGCHLD from non-workload processes

The function trace__symbols_init() runs "perf-read-vdso32" and that ends up
with a SIGCHLD delivered to 'perf'. And this SIGCHLD make perf exit early.

'perf trace' should exit only if the SIGCHLD is from our workload process.
So let's use sigaction() instead of signal() to match such condition.

Committer notes:

Use memset to zero the 'struct sigaction' variable as the '= { 0 }'
method isn't accepted in many compiler versions, e.g.:

4 34.02 alpine:3.6 : FAIL clang version 4.0.0 (tags/RELEASE_400/final)
builtin-trace.c:4897:35: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
struct sigaction sigchld_act = { 0 };
^
{}
builtin-trace.c:4897:37: error: missing field 'sa_mask' initializer [-Werror,-Wmissing-field-initializers]
struct sigaction sigchld_act = { 0 };
^
2 errors generated.
6 32.60 alpine:3.8 : FAIL gcc version 6.4.0 (Alpine 6.4.0)
builtin-trace.c:4897:35: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
struct sigaction sigchld_act = { 0 };
^
{}
builtin-trace.c:4897:37: error: missing field 'sa_mask' initializer [-Werror,-Wmissing-field-initializers]
struct sigaction sigchld_act = { 0 };
^
2 errors generated.
7 34.82 alpine:3.9 : FAIL gcc version 8.3.0 (Alpine 8.3.0)
builtin-trace.c:4897:35: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
struct sigaction sigchld_act = { 0 };
^
{}
builtin-trace.c:4897:37: error: missing field 'sa_mask' initializer [-Werror,-Wmissing-field-initializers]
struct sigaction sigchld_act = { 0 };
^
2 errors generated.

Signed-off-by: Changbin Du <changbin.du@gmail.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220208140725.3947-1-changbin.du@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Changbin Du and committed by
Arnaldo Carvalho de Melo
de9f498d 0bc2ba49

+18 -5
+18 -5
tools/perf/builtin-trace.c
··· 1536 1536 return fprintf(fp, " ? "); 1537 1537 } 1538 1538 1539 + static pid_t workload_pid = -1; 1539 1540 static bool done = false; 1540 1541 static bool interrupted = false; 1541 1542 1542 - static void sig_handler(int sig) 1543 + static void sighandler_interrupt(int sig __maybe_unused) 1543 1544 { 1544 - done = true; 1545 - interrupted = sig == SIGINT; 1545 + done = interrupted = true; 1546 + } 1547 + 1548 + static void sighandler_chld(int sig __maybe_unused, siginfo_t *info, 1549 + void *context __maybe_unused) 1550 + { 1551 + if (info->si_pid == workload_pid) 1552 + done = true; 1546 1553 } 1547 1554 1548 1555 static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread, FILE *fp) ··· 3945 3938 bool draining = false; 3946 3939 3947 3940 trace->live = true; 3948 - signal(SIGCHLD, sig_handler); 3949 3941 3950 3942 if (!trace->raw_augmented_syscalls) { 3951 3943 if (trace->trace_syscalls && trace__add_syscall_newtp(trace)) ··· 4024 4018 fprintf(trace->output, "Couldn't run the workload!\n"); 4025 4019 goto out_delete_evlist; 4026 4020 } 4021 + workload_pid = evlist->workload.pid; 4027 4022 } 4028 4023 4029 4024 err = evlist__open(evlist); ··· 4894 4887 const char * const trace_subcommands[] = { "record", NULL }; 4895 4888 int err = -1; 4896 4889 char bf[BUFSIZ]; 4890 + struct sigaction sigchld_act; 4897 4891 4898 4892 signal(SIGSEGV, sighandler_dump_stack); 4899 4893 signal(SIGFPE, sighandler_dump_stack); 4900 - signal(SIGINT, sig_handler); 4894 + signal(SIGINT, sighandler_interrupt); 4895 + 4896 + memset(&sigchld_act, 0, sizeof(sigchld_act)); 4897 + sigchld_act.sa_flags = SA_SIGINFO; 4898 + sigchld_act.sa_sigaction = sighandler_chld; 4899 + sigaction(SIGCHLD, &sigchld_act, NULL); 4901 4900 4902 4901 trace.evlist = evlist__new(); 4903 4902 trace.sctbl = syscalltbl__new();