From 79e6c7dcc896a2cff9ddf64ea5e193ddea6aec88 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 7 Dec 2011 09:13:02 -0500 Subject: [PATCH] commit bash-20070920 snapshot --- CWRU/CWRU.chlog | 7 +++++++ builtins/fc.def | 2 +- doc/bash.1 | 5 +++-- doc/bashref.texi | 2 ++ jobs.c | 13 +++++++++++-- jobs.h | 3 +++ nojobs.c | 31 +++++++++++++++---------------- 7 files changed, 42 insertions(+), 21 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 73707c365..292ac7fa0 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -14893,3 +14893,10 @@ builtins/common.c - if DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS is defined, don't print an error message from sh_wrerror if errno == EPIPE. Suggestion from Petr Sumbera + + 9/19 + ---- +{jobs,nojobs}.c,jobs.h + - add code to retry fork() after EAGAIN, with a progressively longer + sleep between attempts, up to FORKSLEEP_MAX (16) seconds. Suggested + by Martin Koeppe diff --git a/builtins/fc.def b/builtins/fc.def index 5d6d530ea..4ea703077 100644 --- a/builtins/fc.def +++ b/builtins/fc.def @@ -290,7 +290,7 @@ fc_builtin (list) line was actually added (HISTIGNORE may have caused it to not be), so we check hist_last_line_added. */ - /* "When not listing, he fc command that caused the editing shall not be + /* "When not listing, the fc command that caused the editing shall not be entered into the history list." */ if (listing == 0 && hist_last_line_added) delete_last_history (); diff --git a/doc/bash.1 b/doc/bash.1 index 86596ebac..35cbd3833 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -8595,8 +8595,9 @@ none are found. Provides control over the resources available to the shell and to processes started by it, on systems that allow such control. The \fB\-H\fP and \fB\-S\fP options specify that the hard or soft limit is -set for the given resource. A hard limit cannot be increased once it -is set; a soft limit may be increased up to the value of the hard limit. +set for the given resource. +A hard limit cannot be increased by a non-root user once it is set; +a soft limit may be increased up to the value of the hard limit. If neither \fB\-H\fP nor \fB\-S\fP is specified, both the soft and hard limits are set. The value of diff --git a/doc/bashref.texi b/doc/bashref.texi index 7a0c8282a..d34f6370f 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -3655,6 +3655,8 @@ If @var{limit} is given, it is the new value of the specified resource; the special @var{limit} values @code{hard}, @code{soft}, and @code{unlimited} stand for the current hard limit, the current soft limit, and no limit, respectively. +A hard limit cannot be increased by a non-root user once it is set; +a soft limit may be increased up to the value of the hard limit. Otherwise, the current value of the soft limit for the specified resource is printed, unless the @option{-H} option is supplied. When setting new limits, if neither @option{-H} nor @option{-S} is supplied, diff --git a/jobs.c b/jobs.c index d94cc5fa3..82a6b488d 100644 --- a/jobs.c +++ b/jobs.c @@ -1674,6 +1674,7 @@ make_child (command, async_p) char *command; int async_p; { + int forksleep; sigset_t set, oset; pid_t pid; @@ -1695,8 +1696,16 @@ make_child (command, async_p) sync_buffered_stream (default_buffered_input); #endif /* BUFFERED_INPUT */ - /* Create the child, handle severe errors. */ - if ((pid = fork ()) < 0) + /* Create the child, handle severe errors. Retry on EAGAIN. */ + while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX) + { + sys_error ("fork: retry"); + if (sleep (forksleep) != 0) + break; + forksleep <<= 1; + } + + if (pid < 0) { sys_error ("fork"); diff --git a/jobs.h b/jobs.h index 17f038798..91dfa03e3 100644 --- a/jobs.h +++ b/jobs.h @@ -38,6 +38,9 @@ /* I looked it up. For pretty_print_job (). The real answer is 24. */ #define LONGEST_SIGNAL_DESC 24 +/* The max time to sleep while retrying fork() on EAGAIN failure */ +#define FORKSLEEP_MAX 16 + /* We keep an array of jobs. Each entry in the array is a linked list of processes that are piped together. The first process encountered is the group leader. */ diff --git a/nojobs.c b/nojobs.c index e626b2c7a..059c89ace 100644 --- a/nojobs.c +++ b/nojobs.c @@ -465,9 +465,7 @@ make_child (command, async_p) int async_p; { pid_t pid; -#if defined (HAVE_WAITPID) - int retry = 1; -#endif /* HAVE_WAITPID */ + int forksleep; /* Discard saved memory. */ if (command) @@ -484,26 +482,27 @@ make_child (command, async_p) sync_buffered_stream (default_buffered_input); #endif /* BUFFERED_INPUT */ - /* Create the child, handle severe errors. */ -#if defined (HAVE_WAITPID) - retry_fork: -#endif /* HAVE_WAITPID */ - - if ((pid = fork ()) < 0) + /* Create the child, handle severe errors. Retry on EAGAIN. */ + forksleep = 1; + while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX) { + sys_error ("fork: retry"); #if defined (HAVE_WAITPID) /* Posix systems with a non-blocking waitpid () system call available get another chance after zombies are reaped. */ - if (errno == EAGAIN && retry) - { - reap_zombie_children (); - retry = 0; - goto retry_fork; - } + reap_zombie_children (); + if (forksleep > 1 && sleep (forksleep) != 0) + break; +#else + if (sleep (forksleep) != 0) + break; #endif /* HAVE_WAITPID */ + forksleep <<= 1; + } + if (pid < 0) + { sys_error ("fork"); - throw_to_top_level (); } -- 2.47.3