aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2022-09-21 19:13:45 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2022-09-29 18:12:37 +0100
commita711987490a1784c3e3fd6d752a63501c11eb80b (patch)
tree6ece2528ad196837fb3f7929558d9a0d335d6511 /tools
parentkselftest/arm64: Flag fp-stress as exiting when we begin finishing up (diff)
downloadlinux-dev-a711987490a1784c3e3fd6d752a63501c11eb80b.tar.xz
linux-dev-a711987490a1784c3e3fd6d752a63501c11eb80b.zip
kselftest/arm64: Handle EINTR while reading data from children
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> Link: https://lore.kernel.org/r/20220921181345.618085-4-broonie@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/arm64/fp/fp-stress.c85
1 files 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;