|
4 | 4 | #include <unistd.h> |
5 | 5 | #include <iterator> |
6 | 6 | #include <sys/wait.h> |
| 7 | +#include <errno.h> |
7 | 8 | #include "std_compat/memory.h" |
8 | 9 |
|
9 | 10 | struct external_forkexec: public libpressio_launch_plugin { |
@@ -36,6 +37,7 @@ extern_proc_results launch(std::vector<std::string> const& full_command) const o |
36 | 37 | case 0: |
37 | 38 | //in the child process |
38 | 39 | { |
| 40 | + close(STDIN_FILENO); |
39 | 41 | close(stdout_pipe_fd[0]); |
40 | 42 | close(stderr_pipe_fd[0]); |
41 | 43 | dup2(stdout_pipe_fd[1], 1); |
@@ -78,21 +80,72 @@ extern_proc_results launch(std::vector<std::string> const& full_command) const o |
78 | 80 | char buffer[2048]; |
79 | 81 | std::ostringstream stdout_stream; |
80 | 82 | std::ostringstream stderr_stream; |
81 | | - do { |
82 | | - //read the stdout[0] |
83 | | - int nread; |
84 | | - while((nread = read(stdout_pipe_fd[0], buffer, 2048)) > 0) { |
85 | | - stdout_stream.write(buffer, nread); |
| 83 | + bool stdout_closed = false, stderr_closed = false; |
| 84 | + |
| 85 | + while(true) { |
| 86 | + int ready, nfds = 0; |
| 87 | + ssize_t nread; |
| 88 | + fd_set readfds, writefds, exceptfds; |
| 89 | + |
| 90 | + FD_ZERO(&readfds); |
| 91 | + FD_ZERO(&writefds); |
| 92 | + FD_ZERO(&exceptfds); |
| 93 | + if(not stdout_closed) { |
| 94 | + FD_SET(stdout_pipe_fd[0], &readfds); |
| 95 | + nfds = std::max(stdout_pipe_fd[0], nfds); |
86 | 96 | } |
87 | | - |
88 | | - //read the stderr[0] |
89 | | - while((nread = read(stderr_pipe_fd[0], buffer, 2048)) > 0) { |
90 | | - stderr_stream.write(buffer, nread); |
| 97 | + if(not stderr_closed) { |
| 98 | + FD_SET(stderr_pipe_fd[0], &readfds); |
| 99 | + nfds = std::max(stderr_pipe_fd[0], nfds); |
91 | 100 | } |
92 | 101 |
|
93 | | - //wait for the child to complete |
94 | | - waitpid(child, &status, 0); |
95 | | - } while (not WIFEXITED(status)); |
| 102 | + if(stdout_closed && stderr_closed) { |
| 103 | + break; |
| 104 | + } |
| 105 | + |
| 106 | + ready = select(nfds+1, &readfds, &writefds, &exceptfds, nullptr); |
| 107 | + |
| 108 | + if(ready == -1 && errno == EINTR) { |
| 109 | + continue; |
| 110 | + } |
| 111 | + |
| 112 | + if(!stdout_closed && FD_ISSET(stdout_pipe_fd[0], &readfds)) { |
| 113 | + nread = read(stdout_pipe_fd[0], buffer, sizeof buffer); |
| 114 | + if(nread > 0) { |
| 115 | + stdout_stream.write(buffer, nread); |
| 116 | + } else if (nread == 0) { |
| 117 | + stdout_closed = true; |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + if(!stderr_closed && FD_ISSET(stderr_pipe_fd[0], &readfds)) { |
| 122 | + nread = read(stderr_pipe_fd[0], buffer, sizeof buffer); |
| 123 | + if(nread > 0) { |
| 124 | + stderr_stream.write(buffer, nread); |
| 125 | + } else if(nread == 0) { |
| 126 | + stderr_closed = true; |
| 127 | + } |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + waitpid(child, &status, 0); |
| 132 | + close(stdout_pipe_fd[0]); |
| 133 | + close(stderr_pipe_fd[0]); |
| 134 | +// do { |
| 135 | +// //read the stdout[0] |
| 136 | +// int nread; |
| 137 | +// while((nread = read(stdout_pipe_fd[0], buffer, 2048)) > 0) { |
| 138 | +// stdout_stream.write(buffer, nread); |
| 139 | +// } |
| 140 | +// |
| 141 | +// //read the stderr[0] |
| 142 | +// while((nread = read(stderr_pipe_fd[0], buffer, 2048)) > 0) { |
| 143 | +// stderr_stream.write(buffer, nread); |
| 144 | +// } |
| 145 | +// |
| 146 | +// //wait for the child to complete |
| 147 | +// waitpid(child, &status, 0); |
| 148 | +// } while (not WIFEXITED(status)); |
96 | 149 |
|
97 | 150 | results.proc_stdout = stdout_stream.str(); |
98 | 151 | results.proc_stderr = stderr_stream.str(); |
|
0 commit comments