Skip to content

Commit d509d14

Browse files
captain5050namhyung
authored andcommitted
perf stat: Improve handling of termination by signal
When interrupting perf stat in repeat mode with a signal the signal is passed to the child process but the repeat doesn't terminate: ``` $ perf stat -v --null --repeat 10 sleep 1 Control descriptor is not initialized [ perf stat: executing run #1 ... ] [ perf stat: executing run #2 ... ] ^Csleep: Interrupt [ perf stat: executing run #3 ... ] [ perf stat: executing run #4 ... ] [ perf stat: executing run #5 ... ] [ perf stat: executing run #6 ... ] [ perf stat: executing run #7 ... ] [ perf stat: executing run #8 ... ] [ perf stat: executing run #9 ... ] [ perf stat: executing run #10 ... ] Performance counter stats for 'sleep 1' (10 runs): 0.9500 +- 0.0512 seconds time elapsed ( +- 5.39% ) 0.01user 0.02system 0:09.53elapsed 0%CPU (0avgtext+0avgdata 18940maxresident)k 29944inputs+0outputs (0major+2629minor)pagefaults 0swaps ``` Terminate the repeated run and give a reasonable exit value: ``` $ perf stat -v --null --repeat 10 sleep 1 Control descriptor is not initialized [ perf stat: executing run #1 ... ] [ perf stat: executing run #2 ... ] [ perf stat: executing run #3 ... ] ^Csleep: Interrupt Performance counter stats for 'sleep 1' (10 runs): 0.680 +- 0.321 seconds time elapsed ( +- 47.16% ) Command exited with non-zero status 130 0.00user 0.01system 0:02.05elapsed 0%CPU (0avgtext+0avgdata 70688maxresident)k 0inputs+0outputs (0major+5002minor)pagefaults 0swaps ``` Note, this also changes the exit value for non-repeat runs when interrupted by a signal. Reported-by: Ingo Molnar <mingo@kernel.org> Closes: https://lore.kernel.org/lkml/aS5wjmbAM9ka3M2g@gmail.com/ Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Thomas Richter <tmricht@linux.ibm.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
1 parent 5123509 commit d509d14

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

tools/perf/builtin-stat.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,10 +1007,20 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
10071007
goto err_out;
10081008
}
10091009

1010-
if (WIFSIGNALED(status))
1010+
if (WIFSIGNALED(status)) {
1011+
/*
1012+
* We want to indicate failure to stop a repeat run,
1013+
* hence negative. We want the value to be the exit code
1014+
* of perf, which for termination by a signal is 128
1015+
* plus the signal number.
1016+
*/
1017+
err = 0 - (128 + WTERMSIG(status));
10111018
psignal(WTERMSIG(status), argv[0]);
1019+
} else {
1020+
err = WEXITSTATUS(status);
1021+
}
10121022
} else {
1013-
status = dispatch_events(forks, timeout, interval, &times);
1023+
err = dispatch_events(forks, timeout, interval, &times);
10141024
}
10151025

10161026
disable_counters();
@@ -1050,7 +1060,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
10501060
if (!STAT_RECORD)
10511061
evlist__close(evsel_list);
10521062

1053-
return WEXITSTATUS(status);
1063+
return err;
10541064

10551065
err_out:
10561066
if (forks)
@@ -2969,7 +2979,7 @@ int cmd_stat(int argc, const char **argv)
29692979
evlist__reset_prev_raw_counts(evsel_list);
29702980

29712981
status = run_perf_stat(argc, argv, run_idx);
2972-
if (status == -1)
2982+
if (status < 0)
29732983
break;
29742984

29752985
if (forever && !interval) {
@@ -3039,5 +3049,6 @@ int cmd_stat(int argc, const char **argv)
30393049

30403050
evlist__close_control(stat_config.ctl_fd, stat_config.ctl_fd_ack, &stat_config.ctl_fd_close);
30413051

3042-
return status;
3052+
/* Only the low byte of status becomes the exit code. */
3053+
return abs(status);
30433054
}

0 commit comments

Comments
 (0)