diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-22 21:34:24 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-22 21:34:24 +0000 |
commit | 923a79a7690748f6df3fc3f6d461578cb10e7f88 (patch) | |
tree | ddaf77861737a795a78c5db1b5569a7e7077a596 | |
parent | 30cfdf90ceecad82a378396fad517cb4d3fe7b30 (diff) | |
download | busybox-w32-923a79a7690748f6df3fc3f6d461578cb10e7f88.tar.gz busybox-w32-923a79a7690748f6df3fc3f6d461578cb10e7f88.tar.bz2 busybox-w32-923a79a7690748f6df3fc3f6d461578cb10e7f88.zip |
runsvdir: conditionalize "log in argiment" (mis)feature. By Vladimir.
with:
runsv 139 141 +2
runsvdir_main 1583 1513 -70
without:
warn2_cannot 14 27 +13
runsv 139 141 +2
warnx 28 16 -12
warn3x 23 - -23
runsvdir_main 1583 1125 -458
-rw-r--r-- | runit/Config.in | 9 | ||||
-rw-r--r-- | runit/runsvdir.c | 143 |
2 files changed, 88 insertions, 64 deletions
diff --git a/runit/Config.in b/runit/Config.in index 8a7deea72..beff1e7e2 100644 --- a/runit/Config.in +++ b/runit/Config.in | |||
@@ -20,6 +20,15 @@ config RUNSVDIR | |||
20 | a directory, in the services directory dir, up to a limit of 1000 | 20 | a directory, in the services directory dir, up to a limit of 1000 |
21 | subdirectories, and restarts a runsv process if it terminates. | 21 | subdirectories, and restarts a runsv process if it terminates. |
22 | 22 | ||
23 | config FEATURE_RUNSVDIR_LOG | ||
24 | bool "Enable scrolling argument log" | ||
25 | depends on RUNSVDIR | ||
26 | default n | ||
27 | help | ||
28 | Enable feature where second parameter of runsvdir holds last error | ||
29 | message (viewable via top/ps). Otherwise (feature is off | ||
30 | or no parameter), error messages go to stderr only. | ||
31 | |||
23 | config SV | 32 | config SV |
24 | bool "sv" | 33 | bool "sv" |
25 | default n | 34 | default n |
diff --git a/runit/runsvdir.c b/runit/runsvdir.c index 0dedd5c77..8099ebf5c 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c | |||
@@ -35,8 +35,13 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
35 | 35 | ||
36 | #define MAXSERVICES 1000 | 36 | #define MAXSERVICES 1000 |
37 | 37 | ||
38 | /* Should be not needed - all dirs are on same FS, right? */ | ||
39 | #define CHECK_DEVNO_TOO 0 | ||
40 | |||
38 | struct service { | 41 | struct service { |
42 | #if CHECK_DEVNO_TOO | ||
39 | dev_t dev; | 43 | dev_t dev; |
44 | #endif | ||
40 | ino_t ino; | 45 | ino_t ino; |
41 | pid_t pid; | 46 | pid_t pid; |
42 | smallint isgone; | 47 | smallint isgone; |
@@ -45,28 +50,30 @@ struct service { | |||
45 | struct globals { | 50 | struct globals { |
46 | struct service *sv; | 51 | struct service *sv; |
47 | char *svdir; | 52 | char *svdir; |
48 | char *rplog; | ||
49 | int svnum; | 53 | int svnum; |
54 | #if ENABLE_FEATURE_RUNSVDIR_LOG | ||
55 | char *rplog; | ||
50 | int rploglen; | 56 | int rploglen; |
51 | struct fd_pair logpipe; | 57 | struct fd_pair logpipe; |
52 | struct pollfd pfd[1]; | 58 | struct pollfd pfd[1]; |
53 | unsigned stamplog; | 59 | unsigned stamplog; |
54 | smallint check; /* = 1; */ | 60 | #endif |
61 | smallint need_rescan; /* = 1; */ | ||
55 | smallint set_pgrp; | 62 | smallint set_pgrp; |
56 | }; | 63 | }; |
57 | #define G (*(struct globals*)&bb_common_bufsiz1) | 64 | #define G (*(struct globals*)&bb_common_bufsiz1) |
58 | #define sv (G.sv ) | 65 | #define sv (G.sv ) |
59 | #define svdir (G.svdir ) | 66 | #define svdir (G.svdir ) |
60 | #define rplog (G.rplog ) | 67 | #define svnum (G.svnum ) |
61 | #define svnum (G.svnum ) | 68 | #define rplog (G.rplog ) |
62 | #define rploglen (G.rploglen ) | 69 | #define rploglen (G.rploglen ) |
63 | #define logpipe (G.logpipe ) | 70 | #define logpipe (G.logpipe ) |
64 | #define pfd (G.pfd ) | 71 | #define pfd (G.pfd ) |
65 | #define stamplog (G.stamplog ) | 72 | #define stamplog (G.stamplog ) |
66 | #define check (G.check ) | 73 | #define need_rescan (G.need_rescan ) |
67 | #define set_pgrp (G.set_pgrp ) | 74 | #define set_pgrp (G.set_pgrp ) |
68 | #define INIT_G() do { \ | 75 | #define INIT_G() do { \ |
69 | check = 1; \ | 76 | need_rescan = 1; \ |
70 | } while (0) | 77 | } while (0) |
71 | 78 | ||
72 | static void fatal2_cannot(const char *m1, const char *m2) | 79 | static void fatal2_cannot(const char *m1, const char *m2) |
@@ -82,10 +89,12 @@ static void warn2_cannot(const char *m1, const char *m2) | |||
82 | { | 89 | { |
83 | warn3x("cannot ", m1, m2); | 90 | warn3x("cannot ", m1, m2); |
84 | } | 91 | } |
92 | #if ENABLE_FEATURE_RUNSVDIR_LOG | ||
85 | static void warnx(const char *m1) | 93 | static void warnx(const char *m1) |
86 | { | 94 | { |
87 | warn3x(m1, "", ""); | 95 | warn3x(m1, "", ""); |
88 | } | 96 | } |
97 | #endif | ||
89 | 98 | ||
90 | static void runsv(int no, const char *name) | 99 | static void runsv(int no, const char *name) |
91 | { | 100 | { |
@@ -116,7 +125,7 @@ static void runsv(int no, const char *name) | |||
116 | sv[no].pid = pid; | 125 | sv[no].pid = pid; |
117 | } | 126 | } |
118 | 127 | ||
119 | static void runsvdir(void) | 128 | static void do_rescan(void) |
120 | { | 129 | { |
121 | DIR *dir; | 130 | DIR *dir; |
122 | direntry *d; | 131 | direntry *d; |
@@ -140,13 +149,16 @@ static void runsvdir(void) | |||
140 | continue; | 149 | continue; |
141 | if (stat(d->d_name, &s) == -1) { | 150 | if (stat(d->d_name, &s) == -1) { |
142 | warn2_cannot("stat ", d->d_name); | 151 | warn2_cannot("stat ", d->d_name); |
143 | errno = 0; | ||
144 | continue; | 152 | continue; |
145 | } | 153 | } |
146 | if (!S_ISDIR(s.st_mode)) | 154 | if (!S_ISDIR(s.st_mode)) |
147 | continue; | 155 | continue; |
148 | for (i = 0; i < svnum; i++) { | 156 | for (i = 0; i < svnum; i++) { |
149 | if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { | 157 | if ((sv[i].ino == s.st_ino) |
158 | #if CHECK_DEVNO_TOO | ||
159 | && (sv[i].dev == s.st_dev) | ||
160 | #endif | ||
161 | ) { | ||
150 | sv[i].isgone = 0; | 162 | sv[i].isgone = 0; |
151 | if (!sv[i].pid) | 163 | if (!sv[i].pid) |
152 | runsv(i, d->d_name); | 164 | runsv(i, d->d_name); |
@@ -157,66 +169,43 @@ static void runsvdir(void) | |||
157 | /* new service */ | 169 | /* new service */ |
158 | struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); | 170 | struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); |
159 | if (!svnew) { | 171 | if (!svnew) { |
160 | warn3x("cannot start runsv ", d->d_name, | 172 | warn2_cannot("start runsv ", d->d_name); |
161 | " too many services"); | ||
162 | continue; | 173 | continue; |
163 | } | 174 | } |
164 | sv = svnew; | 175 | sv = svnew; |
165 | svnum++; | 176 | svnum++; |
166 | memset(&sv[i], 0, sizeof(sv[i])); | 177 | memset(&sv[i], 0, sizeof(sv[i])); |
167 | sv[i].ino = s.st_ino; | 178 | sv[i].ino = s.st_ino; |
179 | #if CHECK_DEVNO_TOO | ||
168 | sv[i].dev = s.st_dev; | 180 | sv[i].dev = s.st_dev; |
181 | #endif | ||
169 | /*sv[i].pid = 0;*/ | 182 | /*sv[i].pid = 0;*/ |
170 | /*sv[i].isgone = 0;*/ | 183 | /*sv[i].isgone = 0;*/ |
171 | runsv(i, d->d_name); | 184 | runsv(i, d->d_name); |
172 | check = 1; | 185 | need_rescan = 1; |
173 | } | 186 | } |
174 | } | 187 | } |
175 | if (errno) { | 188 | i = errno; |
189 | closedir(dir); | ||
190 | if (i) { | ||
176 | warn2_cannot("read directory ", svdir); | 191 | warn2_cannot("read directory ", svdir); |
177 | closedir(dir); | 192 | need_rescan = 1; |
178 | check = 1; | ||
179 | return; | 193 | return; |
180 | } | 194 | } |
181 | closedir(dir); | ||
182 | 195 | ||
183 | /* SIGTERM removed runsv's */ | 196 | /* Send SIGTERM to runsv whose directories were not found (removed) */ |
184 | for (i = 0; i < svnum; i++) { | 197 | for (i = 0; i < svnum; i++) { |
185 | if (!sv[i].isgone) | 198 | if (!sv[i].isgone) |
186 | continue; | 199 | continue; |
187 | if (sv[i].pid) | 200 | if (sv[i].pid) |
188 | kill(sv[i].pid, SIGTERM); | 201 | kill(sv[i].pid, SIGTERM); |
189 | sv[i] = sv[--svnum]; | 202 | svnum--; |
190 | /* BUG? we deleted sv[i] by copying over sv[last], but we will not check this newly-copied one! */ | 203 | sv[i] = sv[svnum]; |
191 | check = 1; | 204 | i--; /* so that we don't skip new sv[i] (bug was here!) */ |
205 | need_rescan = 1; | ||
192 | } | 206 | } |
193 | } | 207 | } |
194 | 208 | ||
195 | static int setup_log(void) | ||
196 | { | ||
197 | rploglen = strlen(rplog); | ||
198 | if (rploglen < 7) { | ||
199 | warnx("log must have at least seven characters"); | ||
200 | return 0; | ||
201 | } | ||
202 | if (piped_pair(logpipe)) { | ||
203 | warnx("cannot create pipe for log"); | ||
204 | return -1; | ||
205 | } | ||
206 | close_on_exec_on(logpipe.rd); | ||
207 | close_on_exec_on(logpipe.wr); | ||
208 | ndelay_on(logpipe.rd); | ||
209 | ndelay_on(logpipe.wr); | ||
210 | if (dup2(logpipe.wr, 2) == -1) { | ||
211 | warnx("cannot set filedescriptor for log"); | ||
212 | return -1; | ||
213 | } | ||
214 | pfd[0].fd = logpipe.rd; | ||
215 | pfd[0].events = POLLIN; | ||
216 | stamplog = monotonic_sec(); | ||
217 | return 1; | ||
218 | } | ||
219 | |||
220 | int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 209 | int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
221 | int runsvdir_main(int argc UNUSED_PARAM, char **argv) | 210 | int runsvdir_main(int argc UNUSED_PARAM, char **argv) |
222 | { | 211 | { |
@@ -230,7 +219,6 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
230 | unsigned deadline; | 219 | unsigned deadline; |
231 | unsigned now; | 220 | unsigned now; |
232 | unsigned stampcheck; | 221 | unsigned stampcheck; |
233 | char ch; | ||
234 | int i; | 222 | int i; |
235 | 223 | ||
236 | INIT_G(); | 224 | INIT_G(); |
@@ -241,13 +229,35 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
241 | 229 | ||
242 | bb_signals_recursive((1 << SIGTERM) | (1 << SIGHUP), record_signo); | 230 | bb_signals_recursive((1 << SIGTERM) | (1 << SIGHUP), record_signo); |
243 | svdir = *argv++; | 231 | svdir = *argv++; |
244 | if (argv && *argv) { | 232 | |
233 | #if ENABLE_FEATURE_RUNSVDIR_LOG | ||
234 | /* setup log */ | ||
235 | if (*argv) { | ||
245 | rplog = *argv; | 236 | rplog = *argv; |
246 | if (setup_log() != 1) { | 237 | rploglen = strlen(rplog); |
247 | rplog = 0; | 238 | if (rploglen < 7) { |
248 | warnx("log service disabled"); | 239 | warnx("log must have at least seven characters"); |
240 | } else if (piped_pair(logpipe)) { | ||
241 | warnx("cannot create pipe for log"); | ||
242 | } else { | ||
243 | close_on_exec_on(logpipe.rd); | ||
244 | close_on_exec_on(logpipe.wr); | ||
245 | ndelay_on(logpipe.rd); | ||
246 | ndelay_on(logpipe.wr); | ||
247 | if (dup2(logpipe.wr, 2) == -1) { | ||
248 | warnx("cannot set filedescriptor for log"); | ||
249 | } else { | ||
250 | pfd[0].fd = logpipe.rd; | ||
251 | pfd[0].events = POLLIN; | ||
252 | stamplog = monotonic_sec(); | ||
253 | goto run; | ||
254 | } | ||
249 | } | 255 | } |
256 | rplog = NULL; | ||
257 | warnx("log service disabled"); | ||
250 | } | 258 | } |
259 | run: | ||
260 | #endif | ||
251 | curdir = open_read("."); | 261 | curdir = open_read("."); |
252 | if (curdir == -1) | 262 | if (curdir == -1) |
253 | fatal2_cannot("open current directory", ""); | 263 | fatal2_cannot("open current directory", ""); |
@@ -265,7 +275,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
265 | if (pid == sv[i].pid) { | 275 | if (pid == sv[i].pid) { |
266 | /* runsv has gone */ | 276 | /* runsv has gone */ |
267 | sv[i].pid = 0; | 277 | sv[i].pid = 0; |
268 | check = 1; | 278 | need_rescan = 1; |
269 | break; | 279 | break; |
270 | } | 280 | } |
271 | } | 281 | } |
@@ -277,7 +287,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
277 | stampcheck = now + 1; | 287 | stampcheck = now + 1; |
278 | 288 | ||
279 | if (stat(svdir, &s) != -1) { | 289 | if (stat(svdir, &s) != -1) { |
280 | if (check || s.st_mtime != last_mtime | 290 | if (need_rescan || s.st_mtime != last_mtime |
281 | || s.st_ino != last_ino || s.st_dev != last_dev | 291 | || s.st_ino != last_ino || s.st_dev != last_dev |
282 | ) { | 292 | ) { |
283 | /* svdir modified */ | 293 | /* svdir modified */ |
@@ -285,10 +295,10 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
285 | last_mtime = s.st_mtime; | 295 | last_mtime = s.st_mtime; |
286 | last_dev = s.st_dev; | 296 | last_dev = s.st_dev; |
287 | last_ino = s.st_ino; | 297 | last_ino = s.st_ino; |
288 | check = 0; | 298 | need_rescan = 0; |
289 | //if (now <= mtime) | 299 | //if (now <= mtime) |
290 | // sleep(1); | 300 | // sleep(1); |
291 | runsvdir(); | 301 | do_rescan(); |
292 | while (fchdir(curdir) == -1) { | 302 | while (fchdir(curdir) == -1) { |
293 | warn2_cannot("change directory, pausing", ""); | 303 | warn2_cannot("change directory, pausing", ""); |
294 | sleep(5); | 304 | sleep(5); |
@@ -300,23 +310,28 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
300 | warn2_cannot("stat ", svdir); | 310 | warn2_cannot("stat ", svdir); |
301 | } | 311 | } |
302 | 312 | ||
313 | #if ENABLE_FEATURE_RUNSVDIR_LOG | ||
303 | if (rplog) { | 314 | if (rplog) { |
304 | if ((int)(now - stamplog) >= 0) { | 315 | if ((int)(now - stamplog) >= 0) { |
305 | write(logpipe.wr, ".", 1); | 316 | write(logpipe.wr, ".", 1); |
306 | stamplog = now + 900; | 317 | stamplog = now + 900; |
307 | } | 318 | } |
308 | } | 319 | } |
309 | |||
310 | pfd[0].revents = 0; | 320 | pfd[0].revents = 0; |
321 | #endif | ||
311 | sig_block(SIGCHLD); | 322 | sig_block(SIGCHLD); |
312 | deadline = (check ? 1 : 5); | 323 | deadline = (need_rescan ? 1 : 5); |
324 | #if ENABLE_FEATURE_RUNSVDIR_LOG | ||
313 | if (rplog) | 325 | if (rplog) |
314 | poll(pfd, 1, deadline*1000); | 326 | poll(pfd, 1, deadline*1000); |
315 | else | 327 | else |
328 | #endif | ||
316 | sleep(deadline); | 329 | sleep(deadline); |
317 | sig_unblock(SIGCHLD); | 330 | sig_unblock(SIGCHLD); |
318 | 331 | ||
332 | #if ENABLE_FEATURE_RUNSVDIR_LOG | ||
319 | if (pfd[0].revents & POLLIN) { | 333 | if (pfd[0].revents & POLLIN) { |
334 | char ch; | ||
320 | while (read(logpipe.rd, &ch, 1) > 0) { | 335 | while (read(logpipe.rd, &ch, 1) > 0) { |
321 | if (ch) { | 336 | if (ch) { |
322 | for (i = 6; i < rploglen; i++) | 337 | for (i = 6; i < rploglen; i++) |
@@ -325,7 +340,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
325 | } | 340 | } |
326 | } | 341 | } |
327 | } | 342 | } |
328 | 343 | #endif | |
329 | switch (bb_got_signal) { | 344 | switch (bb_got_signal) { |
330 | case SIGHUP: | 345 | case SIGHUP: |
331 | for (i = 0; i < svnum; i++) | 346 | for (i = 0; i < svnum; i++) |