In order to handle large output add a thread for read from childs using a pipe and remove non-blocking option.
Modify bash unittest to output large data and cover this scenario. [YOCTO #14220] Signed-off-by: Aníbal Limón <[email protected]> --- Makefile | 2 +- tests/data/bash/ptest/run-ptest | 4 +- utils.c | 112 +++++++++++++++++++++----------- 3 files changed, 78 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 3cca17b..1aa1830 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ TEST_DATA=$(shell echo `pwd`/tests/data) all: $(SOURCES) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) - $(CC) $(LDFLAGS) $(OBJECTS) -lutil -o $@ + $(CC) $(LDFLAGS) $(OBJECTS) -pthread -lutil -o $@ tests: $(TEST_SOURCES) $(TEST_EXECUTABLE) diff --git a/tests/data/bash/ptest/run-ptest b/tests/data/bash/ptest/run-ptest index 09f997f..f36e077 100755 --- a/tests/data/bash/ptest/run-ptest +++ b/tests/data/bash/ptest/run-ptest @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash echo "bash" printf "Hello World!,stderr\n" >&2 @@ -7,3 +7,5 @@ printf "Hello World!,stderr2\n" >&2 echo "bash3" echo "bash4" printf "Hello World!,stderr3\n" >&2 + +echo {1..1000000}\\n diff --git a/utils.c b/utils.c index d784736..84cb570 100644 --- a/utils.c +++ b/utils.c @@ -39,6 +39,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <pthread.h> #include <sys/ioctl.h> #include <sys/resource.h> @@ -53,6 +54,11 @@ #define WAIT_CHILD_POLL_TIMEOUT_MS 200 #define WAIT_CHILD_BUF_MAX_SIZE 1024 +static struct { + int fds[2]; + FILE *fps[2]; +} _child_reader; + static inline char * get_stime(char *stime, size_t size, time_t t) { @@ -269,6 +275,44 @@ close_fds(void) } } +static void * +read_child(void *arg) +{ + struct pollfd pfds[2]; + int r; + + pfds[0].fd = _child_reader.fds[0]; + pfds[0].events = POLLIN; + pfds[1].fd = _child_reader.fds[1]; + pfds[1].events = POLLIN; + + do { + r = poll(pfds, 2, WAIT_CHILD_POLL_TIMEOUT_MS); + if (r > 0) { + char buf[WAIT_CHILD_BUF_MAX_SIZE]; + ssize_t n; + + if (pfds[0].revents != 0) { + n = read(_child_reader.fds[0], buf, WAIT_CHILD_BUF_MAX_SIZE); + if (n > 0) + fwrite(buf, (size_t)n, 1, _child_reader.fps[0]); + } + + if (pfds[1].revents != 0) { + n = read(_child_reader.fds[1], buf, WAIT_CHILD_BUF_MAX_SIZE); + if (n > 0) + fwrite(buf, (size_t)n, 1, _child_reader.fps[1]); + } + + } + + fflush(_child_reader.fps[0]); + fflush(_child_reader.fps[1]); + } while (1); + + return NULL; +} + static inline void run_child(char *run_ptest, int fd_stdout, int fd_stderr) { @@ -292,22 +336,15 @@ run_child(char *run_ptest, int fd_stdout, int fd_stderr) } static inline int -wait_child(pid_t pid, int timeout, int *fds, FILE **fps, int *timeouted) +wait_child(pid_t pid, int timeout, int *timeouted) { - struct pollfd pfds[2]; struct timespec sentinel; clockid_t clock = CLOCK_MONOTONIC; int looping = 1; - int r; int status = -1; int waitflags; - pfds[0].fd = fds[0]; - pfds[0].events = POLLIN; - pfds[1].fd = fds[1]; - pfds[1].events = POLLIN; - if (clock_gettime(clock, &sentinel) == -1) { clock = CLOCK_REALTIME; clock_gettime(clock, &sentinel); @@ -332,32 +369,12 @@ wait_child(pid_t pid, int timeout, int *fds, FILE **fps, int *timeouted) if (waitpid(pid, &status, waitflags) == pid) looping = 0; - r = poll(pfds, 2, WAIT_CHILD_POLL_TIMEOUT_MS); - if (r > 0) { - char buf[WAIT_CHILD_BUF_MAX_SIZE]; - ssize_t n; - - if (pfds[0].revents != 0) { - while ((n = read(fds[0], buf, WAIT_CHILD_BUF_MAX_SIZE)) > 0) - fwrite(buf, (size_t)n, 1, fps[0]); - } - - if (pfds[1].revents != 0) { - while ((n = read(fds[1], buf, WAIT_CHILD_BUF_MAX_SIZE)) > 0) { - fflush(fps[0]); - fwrite(buf, (size_t)n, 1, fps[1]); - fflush(fps[1]); - } - } - - clock_gettime(clock, &sentinel); - } + clock_gettime(clock, &sentinel); if (WIFEXITED(status)) status = WEXITSTATUS(status); } - fflush(fps[0]); return status; } @@ -426,6 +443,7 @@ run_ptests(struct ptest_list *head, const struct ptest_options opts, time_t duration; int slave; int pgid = -1; + pthread_t tid; if (opts.xml_filename) { xh = xml_create(ptest_list_length(head), opts.xml_filename); @@ -435,18 +453,32 @@ run_ptests(struct ptest_list *head, const struct ptest_options opts, do { - if ((rc = pipe2(pipefd_stdout, O_NONBLOCK)) == -1) + if ((rc = pipe(pipefd_stdout)) == -1) break; - if ((rc = pipe2(pipefd_stderr, O_NONBLOCK)) == -1) { + if ((rc = pipe(pipefd_stderr)) == -1) { close(pipefd_stdout[0]); close(pipefd_stdout[1]); break; } - fprintf(fp, "START: %s\n", progname); + if (isatty(0) && ioctl(0, TIOCNOTTY) == -1) { fprintf(fp, "ERROR: Unable to detach from controlling tty, %s\n", strerror(errno)); } + + _child_reader.fds[0] = pipefd_stdout[0]; + _child_reader.fds[1] = pipefd_stderr[0]; + _child_reader.fps[0] = fp; + _child_reader.fps[1] = fp_stderr; + rc = pthread_create(&tid, NULL, read_child, NULL); + if (rc != 0) { + fprintf(fp, "ERROR: Failed to create reader thread, %s\n", strerror(errno)); + close(pipefd_stdout[0]); + close(pipefd_stdout[1]); + break; + } + + fprintf(fp, "START: %s\n", progname); PTEST_LIST_ITERATE_START(head, p) char *ptest_dir = strdup(p->run_ptest); if (ptest_dir == NULL) { @@ -485,8 +517,6 @@ run_ptests(struct ptest_list *head, const struct ptest_options opts, } else { int status; - int fds[2]; fds[0] = pipefd_stdout[0]; fds[1] = pipefd_stderr[0]; - FILE *fps[2]; fps[0] = fp; fps[1] = fp_stderr; if (setpgid(child, pgid) == -1) { fprintf(fp, "ERROR: setpgid() failed, %s\n", strerror(errno)); @@ -496,17 +526,20 @@ run_ptests(struct ptest_list *head, const struct ptest_options opts, fprintf(fp, "%s\n", get_stime(stime, GET_STIME_BUF_SIZE, sttime)); fprintf(fp, "BEGIN: %s\n", ptest_dir); - status = wait_child(child, opts.timeout, fds, fps, &timeouted); + + status = wait_child(child, opts.timeout, &timeouted); + + entime = time(NULL); duration = entime - sttime; if (status) { - fprintf(fps[0], "\nERROR: Exit status is %d\n", status); + fprintf(fp, "\nERROR: Exit status is %d\n", status); rc += 1; } - fprintf(fps[0], "DURATION: %d\n", (int) duration); + fprintf(fp, "DURATION: %d\n", (int) duration); if (timeouted) - fprintf(fps[0], "TIMEOUT: %s\n", ptest_dir); + fprintf(fp, "TIMEOUT: %s\n", ptest_dir); if (opts.xml_filename) xml_add_case(xh, status, ptest_dir, timeouted, (int) duration); @@ -517,6 +550,9 @@ run_ptests(struct ptest_list *head, const struct ptest_options opts, PTEST_LIST_ITERATE_END fprintf(fp, "STOP: %s\n", progname); + pthread_cancel(tid); + pthread_join(tid, NULL); + close(pipefd_stdout[0]); close(pipefd_stdout[1]); close(pipefd_stderr[0]); close(pipefd_stderr[1]); } while (0); -- 2.31.0
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#52813): https://lists.yoctoproject.org/g/yocto/message/52813 Mute This Topic: https://lists.yoctoproject.org/mt/81542215/21656 Group Owner: [email protected] Unsubscribe: https://lists.yoctoproject.org/g/yocto/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
