Currently the code can race as there is a read/write thread handling the stdio 
but
there is no guarantee that when the process exits, the thread has handled all 
the
data. This results in output where "END:" isn't actually at the end of the logs
but somewhere in the middle of the output.

Synchronisation is hard. The easiest way I can see to fix this is to have a 
mutex
for the output and then in the main thread, after the child exits, read any 
remaining
data. This avoids concurrent writes corrupting the output and ensures END: is
actually at the end of the test data.

Signed-off-by: Richard Purdie <richard.pur...@linuxfoundation.org>
---
 utils.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/utils.c b/utils.c
index ec57fa4..65b1df3 100644
--- a/utils.c
+++ b/utils.c
@@ -63,6 +63,7 @@ static struct {
        int timeouted;
        pid_t pid;
        int padding1;
+       pthread_mutex_t fd_lock;
 } _child_reader;
 
 static inline char *
@@ -317,12 +318,13 @@ read_child(void *arg)
 
        do {
                r = poll(pfds, 2, _child_reader.timeout*1000);
+               pthread_mutex_lock(&_child_reader.fd_lock);
                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);
+                               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]);
                        }
@@ -338,11 +340,13 @@ read_child(void *arg)
                        // as much data from the system as possible and kill 
the test
                        collect_system_state(_child_reader.fps[0]);
                        _child_reader.timeouted = 1;
+                       pthread_mutex_unlock(&_child_reader.fd_lock);
                        kill(-_child_reader.pid, SIGKILL);
                 }
 
                fflush(_child_reader.fps[0]);
                fflush(_child_reader.fps[1]);
+               pthread_mutex_unlock(&_child_reader.fd_lock);
        } while (1);
 
        return NULL;
@@ -444,6 +448,8 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
        int slave;
        int pgid = -1;
        pthread_t tid;
+       ssize_t n;
+       char buf[WAIT_CHILD_BUF_MAX_SIZE];
 
        if (opts.xml_filename) {
                xh = xml_create(ptest_list_length(head), opts.xml_filename);
@@ -453,10 +459,10 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
 
        do
        {
-               if ((rc = pipe(pipefd_stdout)) == -1)
+               if ((rc = pipe2(pipefd_stdout, O_NONBLOCK)) == -1)
                        break;
 
-               if ((rc = pipe(pipefd_stderr)) == -1) {
+               if ((rc = pipe2(pipefd_stderr, O_NONBLOCK)) == -1) {
                        close(pipefd_stdout[0]);
                        close(pipefd_stdout[1]);
                        break;
@@ -466,6 +472,11 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
                        fprintf(fp, "ERROR: Unable to detach from controlling 
tty, %s\n", strerror(errno));
                }
 
+               if (pthread_mutex_init(&_child_reader.fd_lock, NULL) != 0) {
+                       printf("Failed to init mutex\n");
+                       exit(EXIT_FAILURE);
+               }
+
                _child_reader.fds[0] = pipefd_stdout[0];
                _child_reader.fds[1] = pipefd_stderr[0];
                _child_reader.fps[0] = fp;
@@ -535,8 +546,13 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
                                entime = time(NULL);
                                duration = entime - sttime;
 
-                               /* Now the child has exited, ensure buffers are 
in sync before writing */
+                               pthread_mutex_lock(&_child_reader.fd_lock);
+                               while ((n = read(_child_reader.fds[0], buf, 
WAIT_CHILD_BUF_MAX_SIZE)) > 0)
+                                       fwrite(buf, (size_t)n, 1, 
_child_reader.fps[0]);
+                               while ((n = read(_child_reader.fds[1], buf, 
WAIT_CHILD_BUF_MAX_SIZE)) > 0)
+                                       fwrite(buf, (size_t)n, 1, 
_child_reader.fps[1]);
                                fflush(NULL);
+                               pthread_mutex_unlock(&_child_reader.fd_lock);
 
                                if (status) {
                                        fprintf(fp, "\nERROR: Exit status is 
%d\n", status);
@@ -558,6 +574,7 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
 
                pthread_cancel(tid);
                pthread_join(tid, NULL);
+               pthread_mutex_destroy(&_child_reader.fd_lock);
 
                close(pipefd_stdout[0]); close(pipefd_stdout[1]);
                close(pipefd_stderr[0]); close(pipefd_stderr[1]);
-- 
2.39.2

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#60347): https://lists.yoctoproject.org/g/yocto/message/60347
Mute This Topic: https://lists.yoctoproject.org/mt/99625182/21656
Group Owner: yocto+ow...@lists.yoctoproject.org
Unsubscribe: 
https://lists.yoctoproject.org/g/yocto/leave/6691583/21656/737036229/xyzzy 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to