]> git.itanic.dy.fi Git - rrdd/blob - process.c
Fix count number of children correctly
[rrdd] / process.c
1 #include "process.h"
2 #include "debug.h"
3
4 int child_count = 0;
5
6 int do_fork(void)
7 {
8         int child, error;
9         child = fork();
10         if (child < 0) {
11                 error = errno;
12                 pr_err("fork() failed: %s\n", strerror(error));
13                 return -1;
14         }
15
16         if (child) {
17                 child_count++;
18                 pr_info("Fork %d, child %d\n", child_count, child);
19                 return child;
20         }
21
22         /* reset child's child count */
23         child_count = 0;
24         return 0;
25 }
26
27 int run(const char *cmd, char *const argv[])
28 {
29         int child, error;
30         if ((child = do_fork()))
31             return child;
32
33         execvp(cmd, argv);
34         error = errno;
35         pr_err("Failed to execv command %s: %s\n", cmd, strerror(error));
36         exit(1);
37         return 0;
38 }
39
40 int harvest_zombies(int pid)
41 {
42         int status, error;
43
44         if (child_count == 0)
45                 return 0;
46
47         if (pid)
48                 pr_info("Waiting on pid %d, children left: %d\n", pid, 
49                         child_count);
50
51         pid = waitpid(pid, &status, 0);
52         if (pid < 0) {
53                 error = errno;
54                 pr_err("Error on wait(): %s\n", strerror(error));
55                 child_count--; /* Decrement child count anyway */
56         }
57         else {
58                 child_count--;
59                 pr_info("pid %d: exit code %d. Children left: %d\n", pid,
60                         status, child_count);
61         }
62
63         return 1;
64 }
65
66 /*
67  * Runs a command cmd with params argv, connects stdin and stdout to
68  * readfd and writefd
69  *
70  * Returns the pid of the executed process
71  */
72 int run_piped(const char *cmd, char *const argv[], int *readfd, int *writefd)
73 {
74         int rfd[2], wfd[2], error, pid;
75
76         if (pipe(rfd)) {
77                 error = errno;
78                 pr_err("pipe() failed: %s\n", strerror(error));
79                 return -1;
80         }
81
82         if (pipe(wfd)) {
83                 error = errno;
84                 pr_err("pipe() failed: %s\n", strerror(error));
85                 return -1;
86         }
87
88         pid = do_fork();
89         if (pid) {
90                 close(rfd[1]);
91                 close(wfd[0]);
92                 *readfd = rfd[0];
93                 *writefd = wfd[1];
94                 return pid;
95         }
96
97         close(rfd[0]);
98         close(wfd[1]);
99         dup2(wfd[0], STDIN_FILENO);
100         dup2(rfd[1], STDOUT_FILENO);
101
102         /* Now we have redirected both stdin and stdout to parent process */
103         execvp(cmd, argv);
104         error = errno;
105         pr_err("Failed to execv command %s: %s\n", cmd, strerror(error));
106         exit(1);
107         return 0;
108 }
109
110 /*
111  * Runs a command cmd with params argv, connects stdin and stdout to
112  * readfd and writefd
113  *
114  * Returns the pid of the executed process
115  */
116 int run_piped_stream(const char *cmd, char *const argv[],
117                      FILE **readf, FILE **writef)
118 {
119         int rfd, wfd, pid, error;
120
121         pid = run_piped(cmd, argv, &rfd, &wfd);
122
123         if (readf) {
124                 *readf = fdopen(rfd, "r");
125                 if (*readf == NULL) {
126                         error = errno;
127                         pr_err("Error opening file stream for fd %d: %s\n",
128                                rfd, strerror(error));
129                         return -1;
130                 }
131         }
132
133         if (writef) {
134                 *writef = fdopen(wfd, "w");
135                 if (*writef == NULL) {
136                         error = errno;
137                         pr_err("Error opening file stream for fd %d: %s\n",
138                                wfd, strerror(error));
139                         return -1;
140                 }
141         }
142
143         return pid;
144 }