commit bash-20200408 snapshot

This commit is contained in:
Chet Ramey
2020-04-10 18:26:33 -04:00
parent ea31c00845
commit b3968b54c1
12 changed files with 191 additions and 18 deletions
+27
View File
@@ -7921,3 +7921,30 @@ execute_cmd.c
- execute_in_subshell,execute_simple_command,execute_disk_command:
remove calls to CHECK_SIGTERM, since we don't install a handler
any more
lib/readline/readline.c
- _rl_enable_bracketed_paste: enabled by default for the time being
4/9
---
jobs.h
- JWAIT_WAITING: new flag for wait functions; means only wait for jobs
with the J_WAITING flag set
- J_WAITING: new job flag, part of arg list to `wait -n'
- IS_WAITING(i): job i has the J_WAITING flag set
jobs.c
- wait_for_any_job: if the flags includes JWAIT_WAITING, we only return
jobs with the J_WAITING flag already set; otherwise we skip them.
For `wait -n args' support
builtins/wait.def
- set_waitlist: take a list of jobspecs and set the J_WAITING flag in
each valid job from the list
- unset_waitlist: turn off the J_WAITING flag for all jobs where it's
set
- wait_builtin: if -n is supplied with a list of arguments, set the
J_WAITING flag in each job in the list, call wait_for_any_job with
the JWAIT_WAITING flag, and clean up by calling unset_waitlist().
From a suggestion from Robert Elz <kre@munnari.oz.au> back in 3/2019
(originally in 10/2017)
+1 -1
View File
@@ -4161,7 +4161,7 @@ set_filename_bstab (string)
memset (filename_bstab, 0, sizeof (filename_bstab));
for (s = string; s && *s; s++)
filename_bstab[*s] = 1;
filename_bstab[(unsigned char)*s] = 1;
}
/* Quote a filename using double quotes, single quotes, or backslashes
+75 -4
View File
@@ -1,7 +1,7 @@
This file is wait.def, from which is created wait.c.
It implements the builtin "wait" in Bash.
Copyright (C) 1987-2019 Free Software Foundation, Inc.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -31,8 +31,9 @@ given, waits for all currently active child processes, and the return
status is zero. If ID is a job specification, waits for all processes
in that job's pipeline.
If the -n option is supplied, waits for the next job to terminate and
returns its exit status.
If the -n option is supplied, waits for a single job from the list of IDs,
or, if no IDs are supplied, for the next job to complete and returns its
exit status.
If the -p option is supplied, the process or job identifier of the job
for which the exit status is returned is assigned to the variable VAR
@@ -44,7 +45,8 @@ specified ID to terminate, instead of waiting for it to change status.
Exit Status:
Returns the status of the last ID; fails if ID is invalid or an invalid
option is given.
option is given, or if -n is supplied and the shell has no unwaited-for
children.
$END
$BUILTIN wait
@@ -79,6 +81,7 @@ $END
#include "../execute_cmd.h"
#include "../jobs.h"
#include "../trap.h"
#include "../sig.h"
#include "common.h"
#include "bashgetopt.h"
@@ -87,6 +90,9 @@ extern int wait_signal_received;
procenv_t wait_intr_buf;
int wait_intr_flag;
static int set_waitlist PARAMS((WORD_LIST *));
static void unset_waitlist PARAMS((void));
/* Wait for the pid in LIST to stop or die. If no arguments are given, then
wait for all of the active background processes of the shell and return
0. If a list of pids or job specs are given, return the exit status of
@@ -198,11 +204,22 @@ wait_builtin (list)
#if defined (JOB_CONTROL)
if (nflag)
{
if (list)
{
opt = set_waitlist (list);
if (opt == 0)
WAIT_RETURN (127);
wflags |= JWAIT_WAITING;
}
status = wait_for_any_job (wflags, &pstat);
if (status < 0)
status = 127;
if (vname && status >= 0)
bind_var_to_int (vname, pstat.pid);
if (list)
unset_waitlist ();
WAIT_RETURN (status);
}
#endif
@@ -291,3 +308,57 @@ wait_builtin (list)
WAIT_RETURN (status);
}
#if defined (JOB_CONTROL)
/* Take each valid pid or jobspec in LIST and mark the corresponding job as
J_WAITING, so wait -n knows which jobs to wait for. Return the number of
jobs we found. */
static int
set_waitlist (list)
WORD_LIST *list;
{
sigset_t set, oset;
int job, r, njob;
intmax_t pid;
WORD_LIST *l;
BLOCK_CHILD (set, oset);
njob = 0;
for (l = list; l; l = l->next)
{
job = NO_JOB;
job = (l && legal_number (l->word->word, &pid) && pid == (pid_t) pid)
? get_job_by_pid ((pid_t) pid, 0, 0)
: get_job_spec (l);
if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
{
sh_badjob (l->word->word);
continue;
}
/* We don't check yet to see if one of the desired jobs has already
terminated, but we could. We wait until wait_for_any_job(). This
has the advantage of validating all the arguments. */
if ((jobs[job]->flags & J_WAITING) == 0)
{
njob++;
jobs[job]->flags |= J_WAITING;
}
}
UNBLOCK_CHILD (oset);
return (njob);
}
/* Clean up after a call to wait -n jobs */
static void
unset_waitlist ()
{
int i;
sigset_t set, oset;
BLOCK_CHILD (set, oset);
for (i = 0; i < js.j_jobslots; i++)
if (jobs[i] && (jobs[i]->flags & J_WAITING))
jobs[i]->flags &= ~J_WAITING;
UNBLOCK_CHILD (oset);
}
#endif
+9 -4
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet.ramey@case.edu
.\"
.\" Last Change: Tue Mar 24 16:38:43 EDT 2020
.\" Last Change: Thu Apr 9 11:50:30 EDT 2020
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2020 March 24" "GNU Bash 5.0"
.TH BASH 1 "2020 April 9" "GNU Bash 5.0"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -10863,8 +10863,13 @@ is not given,
the last-executed process substitution, if its process id is the same as
\fB$!\fP,
and the return status is zero.
If the \fB\-n\fP option is supplied, \fBwait\fP waits for a single job
to terminate and returns its exit status.
If the \fB\-n\fP option is supplied,
\fBwait\fP waits for a single job
from the list of \fIid\fPs or, if no \fIid\fPs are supplied, any job,
to complete and returns its exit status.
If none of the supplied arguments is a child of the shell, or if no arguments
are supplied and the shell has no unwaited-for children, the exit status
is 127.
If the \fB\-p\fP option is supplied, the process or job identifier of the job
for which the exit status is returned is assigned to the variable
\fIvarname\fP named by the option argument.
+6 -1
View File
@@ -8227,7 +8227,12 @@ the last-executed process substitution, if its process id is the same as
@var{$!},
and the return status is zero.
If the @option{-n} option is supplied, @code{wait} waits for a single job
to terminate and returns its exit status.
from the list of @var{pids} or @var{jobspecs} or, if no arguments are
supplied, any job,
to complete and returns its exit status.
If none of the supplied arguments is a child of the shell, or if no arguments
are supplied and the shell has no unwaited-for children, the exit status
is 127.
If the @option{-p} option is supplied, the process or job identifier of the job
for which the exit status is returned is assigned to the variable
@var{varname} named by the option argument.
+3 -3
View File
@@ -2,10 +2,10 @@
Copyright (C) 1988-2020 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Tue Mar 24 16:38:56 EDT 2020
@set LASTCHANGE Thu Apr 9 11:58:06 EDT 2020
@set EDITION 5.0
@set VERSION 5.0
@set UPDATED 24 March 2020
@set UPDATED-MONTH March 2020
@set UPDATED 9 April 2020
@set UPDATED-MONTH April 2020
+8 -2
View File
@@ -3286,6 +3286,8 @@ wait_for_any_job (flags, ps)
BLOCK_CHILD (set, oset);
for (i = 0; i < js.j_jobslots; i++)
{
if ((flags & JWAIT_WAITING) && jobs[i] && IS_WAITING (i) == 0)
continue; /* if we don't want it, skip it */
if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i) == 0)
{
return_job:
@@ -3336,8 +3338,12 @@ return_job:
/* Now we see if we have any dead jobs and return the first one */
BLOCK_CHILD (set, oset);
for (i = 0; i < js.j_jobslots; i++)
if (jobs[i] && DEADJOB (i))
goto return_job;
{
if ((flags & JWAIT_WAITING) && jobs[i] && IS_WAITING (i) == 0)
continue; /* if we don't want it, skip it */
if (jobs[i] && DEADJOB (i))
goto return_job;
}
UNBLOCK_CHILD (oset);
}
+3
View File
@@ -42,6 +42,7 @@
#define JWAIT_PERROR 0x01
#define JWAIT_FORCE 0x02
#define JWAIT_NOWAIT 0x04 /* don't waitpid(), just return status if already exited */
#define JWAIT_WAITING 0x08 /* wait for jobs marked J_WAITING only */
/* The max time to sleep while retrying fork() on EAGAIN failure */
#define FORKSLEEP_MAX 16
@@ -105,11 +106,13 @@ typedef enum { JNONE = -1, JRUNNING = 1, JSTOPPED = 2, JDEAD = 4, JMIXED = 8 } J
#define J_STATSAVED 0x10 /* A process in this job had status saved via $! */
#define J_ASYNC 0x20 /* Job was started asynchronously */
#define J_PIPEFAIL 0x40 /* pipefail set when job was started */
#define J_WAITING 0x80 /* one of a list of jobs for which we are waiting */
#define IS_FOREGROUND(j) ((jobs[j]->flags & J_FOREGROUND) != 0)
#define IS_NOTIFIED(j) ((jobs[j]->flags & J_NOTIFIED) != 0)
#define IS_JOBCONTROL(j) ((jobs[j]->flags & J_JOBCONTROL) != 0)
#define IS_ASYNC(j) ((jobs[j]->flags & J_ASYNC) != 0)
#define IS_WAITING(j) ((jobs[j]->flags & J_WAITING) != 0)
typedef struct job {
char *wd; /* The working directory at time of invocation. */
+4 -1
View File
@@ -1375,9 +1375,12 @@ bind_bracketed_paste_prefix (void)
_rl_keymap = emacs_standard_keymap;
rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin);
#if defined (VI_MODE)
_rl_keymap = vi_insertion_keymap;
rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin);
/* XXX - is there a reason to do this in the vi command keymap? */
#endif
_rl_keymap = xkeymap;
}
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+4
View File
@@ -27,6 +27,10 @@ i killed it
12
[1]- Running sleep 20 &
[3]+ Running sleep 20 &
5: ok 1
./jobs5.sub: line 40: wait: %8: no such job
2: ok 2
2: ok 3
child1 exit status 0
0
./jobs.tests: line 38: wait: %1: no such job
+50 -1
View File
@@ -1,12 +1,61 @@
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# framework to test new `wait -n' option that waits for any job to finish
set -m
sleep 20 &
{ sleep 5; exit 12; } &
{ sleep 2; exit 12; } &
sleep 20 &
wait -n
echo $?
jobs
disown -a
{ sleep 1 ; exit 4; } &
{ sleep 2 ; exit 5; } & bgpid1=$!
{ sleep 4 ; exit 6; } &
wait -p wvar -n %2 %3
case "$wvar" in
$bgpid1) echo $?: ok 1;;
*) echo bad 1;;
esac
{ sleep 1 ; exit 2; } & bgpid2=$!
wait -p wvar -n %8 $!
case $wvar in
$bgpid2) echo $?: ok 2;;
*) echo bad 2;;
esac
disown -a
{ sleep 3; exit 1; } & { sleep 1; exit 2; } & bgpid3=$!
{ sleep 3; exit 3; } & { sleep 3; exit 4; } &
wait -n -p wpid %1 %2 %3 %4
case $wpid in
$bgpid3) echo $?: ok 3;;
*) echo bad 3 ;;
esac
disown -a
unset bgpid1 bgpid2 bgpid3
unset wpid