aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-10-29 12:04:45 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-10-29 12:04:45 +0000
commit6a2c2cf6f3b4f03e18a0118f62f1ebc762ad35a3 (patch)
treedb1f98325b4a545c424ad7097a170aeadefe7aea
parente7368f16fac4ace9474090c9d1f58a145db92650 (diff)
downloadbusybox-w32-6a2c2cf6f3b4f03e18a0118f62f1ebc762ad35a3.tar.gz
busybox-w32-6a2c2cf6f3b4f03e18a0118f62f1ebc762ad35a3.tar.bz2
busybox-w32-6a2c2cf6f3b4f03e18a0118f62f1ebc762ad35a3.zip
runsvdir: fx a recent vda's buglet (was pausing even if not signaled).
stop spawning children immediately if signaled. Kill one global.
-rw-r--r--runit/runsvdir.c76
1 files changed, 42 insertions, 34 deletions
diff --git a/runit/runsvdir.c b/runit/runsvdir.c
index 29e747fc1..e7f8d5ac9 100644
--- a/runit/runsvdir.c
+++ b/runit/runsvdir.c
@@ -58,7 +58,6 @@ struct globals {
58 struct pollfd pfd[1]; 58 struct pollfd pfd[1];
59 unsigned stamplog; 59 unsigned stamplog;
60#endif 60#endif
61 smallint need_rescan; /* = 1; */
62 smallint set_pgrp; 61 smallint set_pgrp;
63}; 62};
64#define G (*(struct globals*)&bb_common_bufsiz1) 63#define G (*(struct globals*)&bb_common_bufsiz1)
@@ -70,10 +69,8 @@ struct globals {
70#define logpipe (G.logpipe ) 69#define logpipe (G.logpipe )
71#define pfd (G.pfd ) 70#define pfd (G.pfd )
72#define stamplog (G.stamplog ) 71#define stamplog (G.stamplog )
73#define need_rescan (G.need_rescan )
74#define set_pgrp (G.set_pgrp ) 72#define set_pgrp (G.set_pgrp )
75#define INIT_G() do { \ 73#define INIT_G() do { \
76 need_rescan = 1; \
77} while (0) 74} while (0)
78 75
79static void fatal2_cannot(const char *m1, const char *m2) 76static void fatal2_cannot(const char *m1, const char *m2)
@@ -96,21 +93,27 @@ static void warnx(const char *m1)
96} 93}
97#endif 94#endif
98 95
99static void runsv(int no, const char *name) 96/* inlining + vfork -> bigger code */
97static NOINLINE pid_t runsv(const char *name)
100{ 98{
101 pid_t pid = vfork(); 99 pid_t pid;
100
101 /* If we got signaled, stop spawning children at once! */
102 if (bb_got_signal)
103 return 0;
102 104
105 pid = vfork();
103 if (pid == -1) { 106 if (pid == -1) {
104 warn2_cannot("vfork", ""); 107 warn2_cannot("vfork", "");
105 return; 108 return 0;
106 } 109 }
107 if (pid == 0) { 110 if (pid == 0) {
108 /* child */ 111 /* child */
109 if (set_pgrp) 112 if (set_pgrp)
110 setsid(); 113 setsid();
111/* man execv: 114/* man execv:
112 * Signals set to be caught by the calling process image 115 * "Signals set to be caught by the calling process image
113 * shall be set to the default action in the new process image. 116 * shall be set to the default action in the new process image."
114 * Therefore, we do not need this: */ 117 * Therefore, we do not need this: */
115#if 0 118#if 0
116 bb_signals(0 119 bb_signals(0
@@ -121,20 +124,22 @@ static void runsv(int no, const char *name)
121 execlp("runsv", "runsv", name, NULL); 124 execlp("runsv", "runsv", name, NULL);
122 fatal2_cannot("start runsv ", name); 125 fatal2_cannot("start runsv ", name);
123 } 126 }
124 sv[no].pid = pid; 127 return pid;
125} 128}
126 129
127static void do_rescan(void) 130/* gcc 4.3.0 does better with NOINLINE */
131static NOINLINE int do_rescan(void)
128{ 132{
129 DIR *dir; 133 DIR *dir;
130 direntry *d; 134 direntry *d;
131 int i; 135 int i;
132 struct stat s; 136 struct stat s;
137 int need_rescan = 0;
133 138
134 dir = opendir("."); 139 dir = opendir(".");
135 if (!dir) { 140 if (!dir) {
136 warn2_cannot("open directory ", svdir); 141 warn2_cannot("open directory ", svdir);
137 return; 142 return 1; /* need to rescan again soon */
138 } 143 }
139 for (i = 0; i < svnum; i++) 144 for (i = 0; i < svnum; i++)
140 sv[i].isgone = 1; 145 sv[i].isgone = 1;
@@ -152,47 +157,47 @@ static void do_rescan(void)
152 } 157 }
153 if (!S_ISDIR(s.st_mode)) 158 if (!S_ISDIR(s.st_mode))
154 continue; 159 continue;
160 /* Do we have this service listed already? */
155 for (i = 0; i < svnum; i++) { 161 for (i = 0; i < svnum; i++) {
156 if ((sv[i].ino == s.st_ino) 162 if ((sv[i].ino == s.st_ino)
157#if CHECK_DEVNO_TOO 163#if CHECK_DEVNO_TOO
158 && (sv[i].dev == s.st_dev) 164 && (sv[i].dev == s.st_dev)
159#endif 165#endif
160 ) { 166 ) {
161 sv[i].isgone = 0; 167 if (sv[i].pid == 0) /* restart if it has died */
162 if (!sv[i].pid) 168 goto run_ith_sv;
163 runsv(i, d->d_name); 169 sv[i].isgone = 0; /* "we still see you" */
164 break; 170 goto next_dentry;
165 } 171 }
166 } 172 }
167 if (i == svnum) { 173 { /* Not found, make new service */
168 /* new service */
169 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); 174 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
170 if (!svnew) { 175 if (!svnew) {
171 warn2_cannot("start runsv ", d->d_name); 176 warn2_cannot("start runsv ", d->d_name);
177 need_rescan = 1;
172 continue; 178 continue;
173 } 179 }
174 sv = svnew; 180 sv = svnew;
175 svnum++; 181 svnum++;
176 memset(&sv[i], 0, sizeof(sv[i]));
177 sv[i].ino = s.st_ino;
178#if CHECK_DEVNO_TOO 182#if CHECK_DEVNO_TOO
179 sv[i].dev = s.st_dev; 183 sv[i].dev = s.st_dev;
180#endif 184#endif
181 /*sv[i].pid = 0;*/ 185 sv[i].ino = s.st_ino;
182 /*sv[i].isgone = 0;*/ 186 run_ith_sv:
183 runsv(i, d->d_name); 187 sv[i].pid = runsv(d->d_name);
184 need_rescan = 1; 188 sv[i].isgone = 0;
185 } 189 }
190 next_dentry: ;
186 } 191 }
187 i = errno; 192 i = errno;
188 closedir(dir); 193 closedir(dir);
189 if (i) { 194 if (i) { /* readdir failed */
190 warn2_cannot("read directory ", svdir); 195 warn2_cannot("read directory ", svdir);
191 need_rescan = 1; 196 return 1; /* need to rescan again soon */
192 return;
193 } 197 }
194 198
195 /* Send SIGTERM to runsv whose directories were not found (removed) */ 199 /* Send SIGTERM to runsv whose directories
200 * were no longer found (-> must have been removed) */
196 for (i = 0; i < svnum; i++) { 201 for (i = 0; i < svnum; i++) {
197 if (!sv[i].isgone) 202 if (!sv[i].isgone)
198 continue; 203 continue;
@@ -201,8 +206,8 @@ static void do_rescan(void)
201 svnum--; 206 svnum--;
202 sv[i] = sv[svnum]; 207 sv[i] = sv[svnum];
203 i--; /* so that we don't skip new sv[i] (bug was here!) */ 208 i--; /* so that we don't skip new sv[i] (bug was here!) */
204 need_rescan = 1;
205 } 209 }
210 return need_rescan;
206} 211}
207 212
208int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 213int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -219,6 +224,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
219 unsigned now; 224 unsigned now;
220 unsigned stampcheck; 225 unsigned stampcheck;
221 int i; 226 int i;
227 int need_rescan = 1;
222 228
223 INIT_G(); 229 INIT_G();
224 230
@@ -284,10 +290,9 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
284 break; 290 break;
285 for (i = 0; i < svnum; i++) { 291 for (i = 0; i < svnum; i++) {
286 if (pid == sv[i].pid) { 292 if (pid == sv[i].pid) {
287 /* runsv has gone */ 293 /* runsv has died */
288 sv[i].pid = 0; 294 sv[i].pid = 0;
289 need_rescan = 1; 295 need_rescan = 1;
290 break;
291 } 296 }
292 } 297 }
293 } 298 }
@@ -306,19 +311,20 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
306 last_mtime = s.st_mtime; 311 last_mtime = s.st_mtime;
307 last_dev = s.st_dev; 312 last_dev = s.st_dev;
308 last_ino = s.st_ino; 313 last_ino = s.st_ino;
309 need_rescan = 0;
310 //if (now <= mtime) 314 //if (now <= mtime)
311 // sleep(1); 315 // sleep(1);
312 do_rescan(); 316 need_rescan = do_rescan();
313 while (fchdir(curdir) == -1) { 317 while (fchdir(curdir) == -1) {
314 warn2_cannot("change directory, pausing", ""); 318 warn2_cannot("change directory, pausing", "");
315 sleep(5); 319 sleep(5);
316 } 320 }
317 } else 321 } else {
318 warn2_cannot("change directory to ", svdir); 322 warn2_cannot("change directory to ", svdir);
323 }
319 } 324 }
320 } else 325 } else {
321 warn2_cannot("stat ", svdir); 326 warn2_cannot("stat ", svdir);
327 }
322 } 328 }
323 329
324#if ENABLE_FEATURE_RUNSVDIR_LOG 330#if ENABLE_FEATURE_RUNSVDIR_LOG
@@ -354,6 +360,8 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
354 } 360 }
355#endif 361#endif
356 switch (bb_got_signal) { 362 switch (bb_got_signal) {
363 case 0: /* we are not signaled, business as usual */
364 break;
357 case SIGHUP: 365 case SIGHUP:
358 for (i = 0; i < svnum; i++) 366 for (i = 0; i < svnum; i++)
359 if (sv[i].pid) 367 if (sv[i].pid)