Skip to content

Commit c6f570a

Browse files
committed
core-helper: replace stress_redo_fork with stress_retry_fork
The new stress_retry_fork helper performs a fork and retries it if it fails. The retries repeat until timeout, or bogo-ops are reached or SIGALRM occurs. If a non-resource fork failure occurs the retry is stopped. The retries option allows an upper limit to retrying, zero means infinite retries. This new helper allows the ugly retry goto loops in stressors to be removed too. Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
1 parent 2b0cbb2 commit c6f570a

72 files changed

Lines changed: 206 additions & 353 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core-helper.c

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,26 +1452,61 @@ int stress_tty_width_get(void)
14521452
}
14531453

14541454
/*
1455-
* stress_redo_fork()
1456-
* check fork errno (in err) and return true if
1457-
* an immediate fork can be retried due to known
1458-
* error cases that are retryable. Also force a
1459-
* scheduling yield.
1460-
*/
1461-
bool stress_redo_fork(stress_args_t *args, const int err)
1462-
{
1463-
/* Timed out! */
1464-
if (UNLIKELY(stress_time_now() > args->time_end)) {
1465-
stress_continue_set_flag(false);
1466-
return false;
1467-
}
1468-
/* More bogo-ops to go and errors indicate a fork retry? */
1469-
if (LIKELY(stress_continue(args)) &&
1470-
((err == EAGAIN) || (err == EINTR) || (err == ENOMEM))) {
1471-
(void)shim_sched_yield();
1472-
return true;
1455+
* stress_retry_fork()
1456+
* retry fork until we timeout, stress_continue() is false
1457+
* or an unexepcted fork() error occurred. Return the pid
1458+
* and errno set to that of the fork() return.
1459+
*
1460+
* if retries > 0 then retry that many times, else retry forever
1461+
*/
1462+
pid_t stress_retry_fork(stress_args_t *args, const int retries)
1463+
{
1464+
pid_t pid;
1465+
int saved_errno;
1466+
int retry = 0;
1467+
1468+
for (;;) {
1469+
errno = 0;
1470+
pid = fork();
1471+
1472+
/* save error as it gets clobbered */
1473+
saved_errno = errno;
1474+
1475+
/* parent or child, OK fork paths */
1476+
if (LIKELY(pid >= 0))
1477+
break;
1478+
1479+
/* Clock time out */
1480+
if (UNLIKELY(stress_time_now() > args->time_end)) {
1481+
stress_continue_set_flag(false);
1482+
break;
1483+
}
1484+
1485+
/* SIGAALRM or bogos reached? */
1486+
if (!stress_continue(args)) {
1487+
break;
1488+
}
1489+
1490+
/* An unexpected fork errror occurred, bail out */
1491+
if ((saved_errno != EAGAIN) &&
1492+
(saved_errno != EINTR) &&
1493+
(saved_errno != ENOMEM)) {
1494+
break;
1495+
}
1496+
/*
1497+
* fork may have failed because of low resources
1498+
* or interrupt, so do yield sleep and try again
1499+
*/
1500+
if (retries > 0) {
1501+
if (retry++ > retries)
1502+
break;
1503+
} else {
1504+
stress_yield_sleep_ms();
1505+
}
14731506
}
1474-
return false;
1507+
/* errno set to fork()'s errno */
1508+
errno = saved_errno;
1509+
return pid;
14751510
}
14761511

14771512
/*

core-helper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ extern WARN_UNUSED int stress_kernel_release_get(void);
7676
extern WARN_UNUSED pid_t stress_unused_racy_pid_get(const bool fork_test);
7777
extern WARN_UNUSED size_t stress_hostname_length_get(void);
7878
extern WARN_UNUSED int stress_tty_width_get(void);
79-
extern WARN_UNUSED bool stress_redo_fork(stress_args_t *args, const int err);
79+
extern WARN_UNUSED pid_t stress_retry_fork(stress_args_t *args, const int retries);
8080
extern void stress_clear_warn_once(void);
8181
extern WARN_UNUSED size_t stress_flag_permutation(const int flags, int **permutations);
8282
extern CONST WARN_UNUSED int stress_exit_status(const int err);

stress-alarm.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,8 @@ static int stress_alarm(stress_args_t *args)
6666
stress_sync_start_wait(args);
6767
stress_proc_state_set(args->name, STRESS_STATE_RUN);
6868

69-
again:
70-
pid = fork();
69+
pid = stress_retry_fork(args, 0);
7170
if (pid < 0) {
72-
if (stress_redo_fork(args, errno))
73-
goto again;
7471
if (UNLIKELY(!stress_continue(args)))
7572
return EXIT_SUCCESS;
7673
pr_fail("%s: fork failed, errno=%d (%s)\n",

stress-apparmor.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,8 @@ static void apparmor_spawn(
243243
stress_pid_t **s_pids_head,
244244
stress_pid_t *s_pid)
245245
{
246-
again:
247-
s_pid->pid = fork();
246+
s_pid->pid = stress_retry_fork(args, 0);
248247
if (s_pid->pid < 0) {
249-
if (stress_redo_fork(args, errno))
250-
goto again;
251248
return;
252249
} else if (s_pid->pid == 0) {
253250
int ret = EXIT_SUCCESS;

stress-bad-altstack.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,10 @@ static int stress_bad_altstack(stress_args_t *args)
384384
pid_t pid;
385385

386386
(void)stress_mwc32();
387-
again:
388387
if (UNLIKELY(!stress_continue_flag()))
389388
return EXIT_SUCCESS;
390-
pid = fork();
389+
pid = stress_retry_fork(args, 0);
391390
if (pid < 0) {
392-
if (stress_redo_fork(args, errno))
393-
goto again;
394391
if (UNLIKELY(!stress_continue(args)))
395392
return EXIT_SUCCESS;
396393
pr_err("%s: fork failed, errno=%d: (%s)\n",
@@ -424,7 +421,7 @@ static int stress_bad_altstack(stress_args_t *args)
424421
"killer, restarting again "
425422
"(instance %" PRIu32 ")\n",
426423
args->name, args->instance);
427-
goto again;
424+
continue;
428425
}
429426
}
430427
/* expected: child killed itself with SIGSEGV */

stress-bad-ioctl.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -572,11 +572,14 @@ static int stress_bad_ioctl(stress_args_t *args)
572572
do {
573573
pid_t pid;
574574

575-
again:
576-
pid = fork();
575+
pid = stress_retry_fork(args, 0);
577576
if (pid < 0) {
578-
if (stress_redo_fork(args, errno))
579-
goto again;
577+
if (UNLIKELY(!stress_continue(args)))
578+
return EXIT_SUCCESS;
579+
pr_fail("%s: fork failed, errno=%d (%s)\n",
580+
args->name, errno, strerror(errno));
581+
rc = EXIT_FAILURE;
582+
break;
580583
} else if (pid > 0) {
581584
int status;
582585
pid_t wret;

stress-cacheline.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -774,11 +774,8 @@ static int stress_cacheline(stress_args_t *args)
774774
rc = EXIT_NO_RESOURCE;
775775
goto finish;
776776
}
777-
again:
778-
s_pids[i].pid = fork();
777+
s_pids[i].pid = stress_retry_fork(args, 0);
779778
if (s_pids[i].pid < 0) {
780-
if (stress_redo_fork(args, errno))
781-
goto again;
782779
if (UNLIKELY(!stress_continue(args)))
783780
goto finish;
784781
pr_err("%s: fork failed, errno=%d: (%s)\n",

stress-cgroup.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -616,14 +616,8 @@ static int stress_cgroup_mount(stress_args_t *args)
616616
stress_proc_state_set(args->name, STRESS_STATE_RUN);
617617

618618
do {
619-
again:
620-
if (UNLIKELY(!stress_continue_flag()))
621-
break;
622-
623-
pid = fork();
619+
pid = stress_retry_fork(args, 0);
624620
if (pid < 0) {
625-
if (stress_redo_fork(args, errno))
626-
goto again;
627621
if (UNLIKELY(!stress_continue(args)))
628622
goto finish;
629623
pr_err("%s: fork failed, errno=%d (%s)\n",
@@ -651,7 +645,7 @@ static int stress_cgroup_mount(stress_args_t *args)
651645
pr_dbg("%s: assuming killed by OOM killer, "
652646
"restarting again (instance %" PRIu32 ")\n",
653647
args->name, args->instance);
654-
goto again;
648+
continue;
655649
}
656650
} else if (WEXITSTATUS(status) == EXIT_FAILURE) {
657651
pr_fail("%s: child mount/umount failed\n", args->name);

stress-chroot.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,11 +478,17 @@ static int stress_chroot(stress_args_t *args)
478478

479479
do {
480480
pid_t pid;
481-
again:
482-
pid = fork();
481+
482+
pid = stress_retry_fork(args, 0);
483483
if (pid < 0) {
484-
if (stress_redo_fork(args, errno))
485-
goto again;
484+
if (UNLIKELY(!stress_continue(args))) {
485+
ret = EXIT_SUCCESS;
486+
break;
487+
}
488+
pr_fail("%s: fork failed, errno=%d (%s)\n",
489+
args->name, errno, strerror(errno));
490+
ret = EXIT_FAILURE;
491+
break;
486492
} else if (pid == 0) {
487493
stress_proc_state_set(args->name, STRESS_STATE_RUN);
488494
stress_set_oom_adjustment(args, true);

stress-cpu-sched.c

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,6 @@ static void stress_cpu_sched_child_exercise(const pid_t pid, const int cpu)
491491
static void stress_cpu_sched_fork(stress_args_t *args)
492492
{
493493
pid_t pid;
494-
int retry = 0;
495494

496495
stress_cpu_sched_set_handler();
497496

@@ -500,13 +499,8 @@ static void stress_cpu_sched_fork(stress_args_t *args)
500499
if (stress_cpu_sched_hrtimer_sigprocmask(SIG_BLOCK) < 0)
501500
return;
502501
#endif
503-
again:
504-
pid = fork();
502+
pid = stress_retry_fork(args, 10);
505503
if (pid == -1) {
506-
if ((retry++ < 10) && stress_redo_fork(args, errno)) {
507-
(void)shim_usleep_interruptible(50000);
508-
goto again;
509-
}
510504
goto err;
511505
} else if (pid == 0) {
512506
const pid_t child_pid = getpid();
@@ -622,21 +616,15 @@ static int stress_cpu_sched_next_cpu_idx(const int instance, const int last_cpu_
622616
static void stress_cpu_sched_exec(stress_args_t *args, char *exec_prog)
623617
{
624618
pid_t pid;
625-
int retry = 0;
626619

627620
#if defined(HAVE_TIMER_CLOCK_REALTIME)
628621
stress_cpu_sched_hrtimer_set(0);
629622
if (stress_cpu_sched_hrtimer_sigprocmask(SIG_BLOCK) < 0)
630623
return;
631624
#endif
632625

633-
again:
634-
pid = fork();
626+
pid = stress_retry_fork(args, 10);
635627
if (pid < 0) {
636-
if ((retry++ < 10) && stress_redo_fork(args, errno)) {
637-
(void)shim_usleep_interruptible(50000);
638-
goto again;
639-
}
640628
#if defined(HAVE_TIMER_CLOCK_REALTIME)
641629
(void)stress_cpu_sched_hrtimer_sigprocmask(SIG_UNBLOCK);
642630
#endif
@@ -714,15 +702,9 @@ static int stress_cpu_sched_child(stress_args_t *args, void *context)
714702

715703
for (i = 0; LIKELY((i < cpu_sched_procs) && stress_continue(args)); i++) {
716704
pid_t pid;
717-
int retry = 0;
718705

719-
again:
720-
pid = fork();
706+
pid = stress_retry_fork(args, 10);
721707
if (pid < 0) {
722-
if ((retry++ < 10) && stress_redo_fork(args, errno)) {
723-
(void)shim_usleep_interruptible(50000);
724-
goto again;
725-
}
726708
stress_cpu_sched_pids[i].pid = -1;
727709
} else if (pid == 0) {
728710
pid_t mypid = getpid();

0 commit comments

Comments
 (0)