2 #include <sys/select.h>
7 static int child_count = 0;
8 static int parent_count = 0;
9 static int process_count = 0;
11 int get_child_count(void)
16 int get_parent_count(void)
26 pr_err("fork() failed: %m\n");
32 pr_info("Fork %d, child %d\n", child_count, child);
36 /* reset child's child count */
42 int harvest_zombies(int pid)
50 pr_info("Waiting on pid %d, children left: %d\n", pid,
53 pid = waitpid(pid, &status, 0);
55 pr_err("Error on wait(): %m\n");
56 child_count--; /* Decrement child count anyway */
60 pr_info("pid %d: exit code %d. Children left: %d\n", pid,
68 * Runs a command cmd with params argv, connects stdin and stdout to
71 * Returns the pid of the executed process
73 int run_piped(const char *cmd, char *const argv[],
74 int *stdinfd, int *stdoutfd, int *stderrfd)
76 int ifd[2], ofd[2], efd[2], pid;
78 pr_info("Running command %s\n", cmd);
80 if (stdinfd && pipe(ifd)) {
81 pr_err("pipe() failed: %m\n");
85 if (stdoutfd && pipe(ofd)) {
86 pr_err("pipe() failed: %m\n");
90 if (stderrfd && pipe(efd)) {
91 pr_err("pipe() failed: %m\n");
96 if (pid) { /* Parent side */
117 dup2(ifd[0], STDIN_FILENO);
122 dup2(ofd[1], STDOUT_FILENO);
127 dup2(efd[1], STDERR_FILENO);
130 /* Now we have redirected standard streams to parent process */
132 pr_err("Failed to execv command %s: %m\n", cmd);
139 * Runs a command cmd with params argv, connects stdin and stdout to
142 * Returns the pid of the executed process
144 int run_piped_stream(const char *cmd, char *const argv[],
145 FILE **stdinf, FILE **stdoutf, FILE **stderrf)
147 int ifd, ofd, efd, pid;
163 pid = run_piped(cmd, argv, i, o, e);
166 *stdinf = fdopen(ifd, "r");
167 if (*stdinf == NULL) {
168 pr_err("Error opening file stream for fd %d: %m\n",
175 *stdoutf = fdopen(ofd, "r");
176 if (*stdoutf == NULL) {
177 pr_err("Error opening file stream for fd %d: %m\n",
184 *stderrf = fdopen(efd, "r");
185 if (*stderrf == NULL) {
186 pr_err("Error opening file stream for fd %d: %m\n",
196 * Forks a child and executes a command to run on parallel
199 #define max(a,b) (a) < (b) ? (b) : (a)
200 #define BUF_SIZE (128*1024)
201 int run(const char *cmd, char *const argv[])
208 char stdoutstr[32], stderrstr[32], indent[16] = { " " };
210 indent[get_parent_count() + 1] = 0;
212 if ((child = do_fork()))
215 child = run_piped(cmd, argv, NULL, &ofd, &efd);
216 snprintf(stdoutstr, 32, "%sstdout", green_color);
217 snprintf(stderrstr, 32, "%sstderr", red_color);
229 maxfd = max(ofd, efd);
230 error = select(maxfd, &rfds, NULL, NULL, NULL);
233 printf("Error with select: %m\n");
237 if (FD_ISSET(ofd, &rfds)) {
239 bytes = read(ofd, rbuf, BUF_SIZE);
243 if (FD_ISSET(efd, &rfds)) {
245 bytes = read(efd, rbuf, BUF_SIZE);
249 pr_err("select() returned unknown fd\n");
254 pr_err("read() failed: %m\n");
259 * Workaround: When a process had die and it has only
260 * written to stderr, select() doesn't indicate that
261 * there might be something to read in stderr fd. To
262 * work around this issue, we try to read stderr just
263 * in case in order to ensure everything gets read.
266 bytes = read(efd, rbuf, BUF_SIZE);
275 printf("%s[%5d %s] %s: %s%s\n", indent,
276 child, cmd, typestr, sptr, normal_color);
286 harvest_zombies(child);