|
20 | 20 | */
|
21 | 21 |
|
22 | 22 | #include <sys/types.h>
|
| 23 | +#include <sys/wait.h> |
23 | 24 | #include <unistd.h>
|
24 | 25 | #include <stdio.h>
|
25 | 26 |
|
@@ -181,9 +182,6 @@ void set_proc_attrs(const char *fmt, ...)
|
181 | 182 |
|
182 | 183 | /* pid */
|
183 | 184 | pt[process_no].pid=getpid();
|
184 |
| - |
185 |
| - /* for sure the process is running */ |
186 |
| - pt[process_no].flags |= OSS_PROC_IS_RUNNING; |
187 | 185 | }
|
188 | 186 |
|
189 | 187 |
|
@@ -229,9 +227,11 @@ void reset_process_slot( int p_id )
|
229 | 227 | }
|
230 | 228 |
|
231 | 229 |
|
| 230 | +enum {CHLD_STARTING, CHLD_OK, CHLD_FAILED}; |
| 231 | + |
232 | 232 | static __attribute__((__noreturn__)) void child_startup_failed(void)
|
233 | 233 | {
|
234 |
| - lock_release(&pt[process_no].startup_lock); |
| 234 | + atomic_store(&pt[process_no].startup_result, CHLD_FAILED); |
235 | 235 | exit(1);
|
236 | 236 | }
|
237 | 237 |
|
@@ -288,18 +288,12 @@ int internal_fork(const char *proc_desc, unsigned int flags,
|
288 | 288 | }
|
289 | 289 |
|
290 | 290 | pt[new_idx].pid = 0;
|
291 |
| - pt[new_idx].startup_result = -1; |
292 | 291 |
|
293 |
| - if (lock_init(&pt[new_idx].startup_lock) == NULL) { |
294 |
| - LM_CRIT("failed to init startup lock for process %d", new_idx); |
295 |
| - return -1; |
296 |
| - } |
297 |
| - lock_get(&pt[new_idx].startup_lock); |
| 292 | + atomic_init(&pt[new_idx].startup_result, CHLD_STARTING); |
298 | 293 |
|
299 | 294 | if ( (pid=fork())<0 ){
|
300 | 295 | LM_CRIT("cannot fork \"%s\" process (%d: %s)\n",proc_desc,
|
301 | 296 | errno, strerror(errno));
|
302 |
| - lock_destroy(&pt[new_idx].startup_lock); |
303 | 297 | reset_process_slot( new_idx );
|
304 | 298 | return -1;
|
305 | 299 | }
|
@@ -344,25 +338,37 @@ int internal_fork(const char *proc_desc, unsigned int flags,
|
344 | 338 | free_route_lists(sroutes);
|
345 | 339 | sroutes = NULL;
|
346 | 340 | }
|
347 |
| - pt[process_no].startup_result = 0; |
348 |
| - lock_release(&pt[process_no].startup_lock); |
| 341 | + atomic_store(&pt[process_no].startup_result, CHLD_OK); |
349 | 342 | return 0;
|
350 | 343 | }else{
|
351 | 344 | /* parent process */
|
352 |
| - /* wait for the child to complete the start-up */ |
353 |
| - lock_get(&pt[new_idx].startup_lock); |
354 |
| - lock_destroy(&pt[new_idx].startup_lock); |
355 |
| - if (pt[new_idx].startup_result != 0) { |
356 |
| - LM_CRIT("failed to initialize child process %d\n", new_idx); |
357 |
| - reset_process_slot( new_idx ); |
358 |
| - return -1; |
| 345 | + /* wait for the child to complete the critical sectoin of the |
| 346 | + * start-up */ |
| 347 | + while (atomic_load(&pt[new_idx].startup_result) == CHLD_STARTING) { |
| 348 | + int status; |
| 349 | + pid_t result = waitpid(pid, &status, WNOHANG); |
| 350 | + if (result < 0) { |
| 351 | + if (errno == EINTR) |
| 352 | + continue; |
| 353 | + goto child_is_down; |
| 354 | + } |
| 355 | + if (result == 0) { |
| 356 | + // Child has not exited yet |
| 357 | + continue; |
| 358 | + } |
| 359 | + // Child has exited, oops |
| 360 | + goto child_is_down; |
359 | 361 | }
|
360 |
| - /* Do not set PID for child in the main process. Let the child do |
361 |
| - * that as this will act as a marker to tell us that the init |
362 |
| - * sequance of the child proc was completed. |
363 |
| - * pt[new_idx].pid = pid; */ |
| 362 | + if (atomic_load(&pt[new_idx].startup_result) != CHLD_OK) { |
| 363 | + goto child_is_down; |
| 364 | + } |
| 365 | + pt[new_idx].flags |= OSS_PROC_IS_RUNNING; |
364 | 366 | tcp_connect_proc_to_tcp_main( new_idx, 0);
|
365 | 367 | return new_idx;
|
| 368 | +child_is_down: |
| 369 | + LM_CRIT("failed to initialize child process %d\n", new_idx); |
| 370 | + reset_process_slot( new_idx ); |
| 371 | + return -1; |
366 | 372 | }
|
367 | 373 | }
|
368 | 374 |
|
|
0 commit comments