A few small updates for fp-stress, improving the usability with signal handling a bit.
Mark Brown (3): kselftest/arm64: Don't repeat termination handler for fp-stress kselftest/arm64: Flag fp-stress as exiting when we begin finishing up kselftest/arm64: Handle EINTR while reading data from children
tools/testing/selftests/arm64/fp/fp-stress.c | 90 ++++++++++++-------- 1 file changed, 55 insertions(+), 35 deletions(-)
base-commit: ea84edbf08025e592f58b0d9b282777a9ca9fb22
When fp-stress gets a termination signal it sets a flag telling itself to exit and sends a termination signal to all the children. If the flag is set then don't bother repeating this process, it isn't going to accomplish anything other than consume CPU time which can be an issue when running in emulation.
Signed-off-by: Mark Brown broonie@kernel.org --- tools/testing/selftests/arm64/fp/fp-stress.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index a5c0ebef2419..4387c3cacaa7 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -255,6 +255,10 @@ static void handle_exit_signal(int sig, siginfo_t *info, void *context) { int i;
+ /* If we're already exiting then don't signal again */ + if (terminate) + return; + ksft_print_msg("Got signal, exiting...\n");
terminate = true;
Once we have started exiting the termination handler will have the same effect as what we're already running so set the termination flag at that point.
Signed-off-by: Mark Brown broonie@kernel.org --- tools/testing/selftests/arm64/fp/fp-stress.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index 4387c3cacaa7..03ce3936220a 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -522,6 +522,7 @@ int main(int argc, char **argv) }
ksft_print_msg("Finishing up...\n"); + terminate = true;
for (i = 0; i < tests; i++) child_stop(&children[i]);
Currently we treat any error when reading from the child as a failure and don't read any more output from that child as a result. This ignores the fact that it is valid for read() to return EINTR as the error code if there is a signal pending so we could stop handling the output of children, especially during exit when we will get some SIGCHLD signals delivered to us. Fix this by pulling the read handling out into a separate function which returns a flag if reads should be continued and wrapping it in a loop.
Signed-off-by: Mark Brown broonie@kernel.org --- tools/testing/selftests/arm64/fp/fp-stress.c | 85 ++++++++++++-------- 1 file changed, 50 insertions(+), 35 deletions(-)
diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index 03ce3936220a..4e62a9199f97 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -121,55 +121,70 @@ static void child_start(struct child_data *child, const char *program) } }
-static void child_output(struct child_data *child, uint32_t events, - bool flush) +static bool child_output_read(struct child_data *child) { char read_data[1024]; char work[1024]; int ret, len, cur_work, cur_read;
- if (events & EPOLLIN) { - ret = read(child->stdout, read_data, sizeof(read_data)); - if (ret < 0) { - ksft_print_msg("%s: read() failed: %s (%d)\n", - child->name, strerror(errno), errno); - return; - } - len = ret; + ret = read(child->stdout, read_data, sizeof(read_data)); + if (ret < 0) { + if (errno == EINTR) + return true;
- child->output_seen = true; + ksft_print_msg("%s: read() failed: %s (%d)\n", + child->name, strerror(errno), + errno); + return false; + } + len = ret;
- /* Pick up any partial read */ - if (child->output) { - strncpy(work, child->output, sizeof(work) - 1); - cur_work = strnlen(work, sizeof(work)); - free(child->output); - child->output = NULL; - } else { - cur_work = 0; - } + child->output_seen = true;
- cur_read = 0; - while (cur_read < len) { - work[cur_work] = read_data[cur_read++]; + /* Pick up any partial read */ + if (child->output) { + strncpy(work, child->output, sizeof(work) - 1); + cur_work = strnlen(work, sizeof(work)); + free(child->output); + child->output = NULL; + } else { + cur_work = 0; + }
- if (work[cur_work] == '\n') { - work[cur_work] = '\0'; - ksft_print_msg("%s: %s\n", child->name, work); - cur_work = 0; - } else { - cur_work++; - } - } + cur_read = 0; + while (cur_read < len) { + work[cur_work] = read_data[cur_read++];
- if (cur_work) { + if (work[cur_work] == '\n') { work[cur_work] = '\0'; - ret = asprintf(&child->output, "%s", work); - if (ret == -1) - ksft_exit_fail_msg("Out of memory\n"); + ksft_print_msg("%s: %s\n", child->name, work); + cur_work = 0; + } else { + cur_work++; } }
+ if (cur_work) { + work[cur_work] = '\0'; + ret = asprintf(&child->output, "%s", work); + if (ret == -1) + ksft_exit_fail_msg("Out of memory\n"); + } + + return false; +} + +static void child_output(struct child_data *child, uint32_t events, + bool flush) +{ + bool read_more; + + if (events & EPOLLIN) { + do { + read_more = child_output_read(child); + } while (read_more); + } + if (events & EPOLLHUP) { close(child->stdout); child->stdout = -1;
On Wed, 21 Sep 2022 19:13:42 +0100, Mark Brown wrote:
A few small updates for fp-stress, improving the usability with signal handling a bit.
Mark Brown (3): kselftest/arm64: Don't repeat termination handler for fp-stress kselftest/arm64: Flag fp-stress as exiting when we begin finishing up kselftest/arm64: Handle EINTR while reading data from children
[...]
Applied to arm64 (for-next/kselftest), thanks!
[1/3] kselftest/arm64: Don't repeat termination handler for fp-stress https://git.kernel.org/arm64/c/c38d381fff26 [2/3] kselftest/arm64: Flag fp-stress as exiting when we begin finishing up https://git.kernel.org/arm64/c/dd72dd7cd527 [3/3] kselftest/arm64: Handle EINTR while reading data from children https://git.kernel.org/arm64/c/a711987490a1
linux-kselftest-mirror@lists.linaro.org