diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-29 12:04:45 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-29 12:04:45 +0000 |
commit | 6a2c2cf6f3b4f03e18a0118f62f1ebc762ad35a3 (patch) | |
tree | db1f98325b4a545c424ad7097a170aeadefe7aea | |
parent | e7368f16fac4ace9474090c9d1f58a145db92650 (diff) | |
download | busybox-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.c | 76 |
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 | ||
79 | static void fatal2_cannot(const char *m1, const char *m2) | 76 | static 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 | ||
99 | static void runsv(int no, const char *name) | 96 | /* inlining + vfork -> bigger code */ |
97 | static 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 | ||
127 | static void do_rescan(void) | 130 | /* gcc 4.3.0 does better with NOINLINE */ |
131 | static 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 | ||
208 | int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 213 | int 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) |