aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-09-22 21:34:24 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-09-22 21:34:24 +0000
commit923a79a7690748f6df3fc3f6d461578cb10e7f88 (patch)
treeddaf77861737a795a78c5db1b5569a7e7077a596
parent30cfdf90ceecad82a378396fad517cb4d3fe7b30 (diff)
downloadbusybox-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.in9
-rw-r--r--runit/runsvdir.c143
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
23config 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
23config SV 32config 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
38struct service { 41struct 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 {
45struct globals { 50struct 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
72static void fatal2_cannot(const char *m1, const char *m2) 79static 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
85static void warnx(const char *m1) 93static void warnx(const char *m1)
86{ 94{
87 warn3x(m1, "", ""); 95 warn3x(m1, "", "");
88} 96}
97#endif
89 98
90static void runsv(int no, const char *name) 99static 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
119static void runsvdir(void) 128static 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
195static 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
220int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 209int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
221int runsvdir_main(int argc UNUSED_PARAM, char **argv) 210int 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 }
259run:
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++)