182 lines
5.2 KiB
Diff
182 lines
5.2 KiB
Diff
|
From https://ftp.gnu.org/gnu/bash/bash-4.4-patches/bash44-020
|
||
|
|
||
|
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
|
||
|
|
||
|
BASH PATCH REPORT
|
||
|
=================
|
||
|
|
||
|
Bash-Release: 4.4
|
||
|
Patch-ID: bash44-020
|
||
|
|
||
|
Bug-Reported-by: Graham Northup <northug@clarkson.edu>
|
||
|
Bug-Reference-ID: <537530c3-61f0-349b-9de6-fa4e2487f428@clarkson.edu>
|
||
|
Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2017-02/msg00025.html
|
||
|
|
||
|
Bug-Description:
|
||
|
|
||
|
In circumstances involving long-running scripts that create and reap many
|
||
|
processes, it is possible for the hash table bash uses to store exit
|
||
|
statuses from asynchronous processes to develop loops. This patch fixes
|
||
|
the loop causes and adds code to detect any future loops.
|
||
|
|
||
|
Patch (apply with `patch -p0'):
|
||
|
|
||
|
*** bash-4.4-patched/jobs.c 2016-11-11 13:42:55.000000000 -0500
|
||
|
--- b/jobs.c 2017-02-22 15:16:28.000000000 -0500
|
||
|
***************
|
||
|
*** 813,818 ****
|
||
|
struct pidstat *ps;
|
||
|
|
||
|
! bucket = pshash_getbucket (pid);
|
||
|
! psi = bgp_getindex ();
|
||
|
ps = &bgpids.storage[psi];
|
||
|
|
||
|
--- b/796,815 ----
|
||
|
struct pidstat *ps;
|
||
|
|
||
|
! /* bucket == existing chain of pids hashing to same value
|
||
|
! psi = where were going to put this pid/status */
|
||
|
!
|
||
|
! bucket = pshash_getbucket (pid); /* index into pidstat_table */
|
||
|
! psi = bgp_getindex (); /* bgpids.head, index into storage */
|
||
|
!
|
||
|
! /* XXX - what if psi == *bucket? */
|
||
|
! if (psi == *bucket)
|
||
|
! {
|
||
|
! #ifdef DEBUG
|
||
|
! internal_warning ("hashed pid %d (pid %d) collides with bgpids.head, skipping", psi, pid);
|
||
|
! #endif
|
||
|
! bgpids.storage[psi].pid = NO_PID; /* make sure */
|
||
|
! psi = bgp_getindex (); /* skip to next one */
|
||
|
! }
|
||
|
!
|
||
|
ps = &bgpids.storage[psi];
|
||
|
|
||
|
***************
|
||
|
*** 842,845 ****
|
||
|
--- b/839,843 ----
|
||
|
{
|
||
|
struct pidstat *ps;
|
||
|
+ ps_index_t *bucket;
|
||
|
|
||
|
ps = &bgpids.storage[psi];
|
||
|
***************
|
||
|
*** 847,856 ****
|
||
|
return;
|
||
|
|
||
|
! if (ps->bucket_next != NO_PID)
|
||
|
bgpids.storage[ps->bucket_next].bucket_prev = ps->bucket_prev;
|
||
|
! if (ps->bucket_prev != NO_PID)
|
||
|
bgpids.storage[ps->bucket_prev].bucket_next = ps->bucket_next;
|
||
|
else
|
||
|
! *(pshash_getbucket (ps->pid)) = ps->bucket_next;
|
||
|
}
|
||
|
|
||
|
--- b/845,861 ----
|
||
|
return;
|
||
|
|
||
|
! if (ps->bucket_next != NO_PIDSTAT)
|
||
|
bgpids.storage[ps->bucket_next].bucket_prev = ps->bucket_prev;
|
||
|
! if (ps->bucket_prev != NO_PIDSTAT)
|
||
|
bgpids.storage[ps->bucket_prev].bucket_next = ps->bucket_next;
|
||
|
else
|
||
|
! {
|
||
|
! bucket = pshash_getbucket (ps->pid);
|
||
|
! *bucket = ps->bucket_next; /* deleting chain head in hash table */
|
||
|
! }
|
||
|
!
|
||
|
! /* clear out this cell, just in case */
|
||
|
! ps->pid = NO_PID;
|
||
|
! ps->bucket_next = ps->bucket_prev = NO_PIDSTAT;
|
||
|
}
|
||
|
|
||
|
***************
|
||
|
*** 859,863 ****
|
||
|
pid_t pid;
|
||
|
{
|
||
|
! ps_index_t psi;
|
||
|
|
||
|
if (bgpids.storage == 0 || bgpids.nalloc == 0 || bgpids.npid == 0)
|
||
|
--- b/864,868 ----
|
||
|
pid_t pid;
|
||
|
{
|
||
|
! ps_index_t psi, orig_psi;
|
||
|
|
||
|
if (bgpids.storage == 0 || bgpids.nalloc == 0 || bgpids.npid == 0)
|
||
|
***************
|
||
|
*** 865,871 ****
|
||
|
|
||
|
/* Search chain using hash to find bucket in pidstat_table */
|
||
|
! for (psi = *(pshash_getbucket (pid)); psi != NO_PIDSTAT; psi = bgpids.storage[psi].bucket_next)
|
||
|
! if (bgpids.storage[psi].pid == pid)
|
||
|
! break;
|
||
|
|
||
|
if (psi == NO_PIDSTAT)
|
||
|
--- b/870,883 ----
|
||
|
|
||
|
/* Search chain using hash to find bucket in pidstat_table */
|
||
|
! for (orig_psi = psi = *(pshash_getbucket (pid)); psi != NO_PIDSTAT; psi = bgpids.storage[psi].bucket_next)
|
||
|
! {
|
||
|
! if (bgpids.storage[psi].pid == pid)
|
||
|
! break;
|
||
|
! if (orig_psi == bgpids.storage[psi].bucket_next) /* catch reported bug */
|
||
|
! {
|
||
|
! internal_warning ("bgp_delete: LOOP: psi (%d) == storage[psi].bucket_next", psi);
|
||
|
! return 0;
|
||
|
! }
|
||
|
! }
|
||
|
|
||
|
if (psi == NO_PIDSTAT)
|
||
|
***************
|
||
|
*** 905,909 ****
|
||
|
pid_t pid;
|
||
|
{
|
||
|
! ps_index_t psi;
|
||
|
|
||
|
if (bgpids.storage == 0 || bgpids.nalloc == 0 || bgpids.npid == 0)
|
||
|
--- b/917,921 ----
|
||
|
pid_t pid;
|
||
|
{
|
||
|
! ps_index_t psi, orig_psi;
|
||
|
|
||
|
if (bgpids.storage == 0 || bgpids.nalloc == 0 || bgpids.npid == 0)
|
||
|
***************
|
||
|
*** 911,917 ****
|
||
|
|
||
|
/* Search chain using hash to find bucket in pidstat_table */
|
||
|
! for (psi = *(pshash_getbucket (pid)); psi != NO_PIDSTAT; psi = bgpids.storage[psi].bucket_next)
|
||
|
! if (bgpids.storage[psi].pid == pid)
|
||
|
! return (bgpids.storage[psi].status);
|
||
|
|
||
|
return -1;
|
||
|
--- b/923,936 ----
|
||
|
|
||
|
/* Search chain using hash to find bucket in pidstat_table */
|
||
|
! for (orig_psi = psi = *(pshash_getbucket (pid)); psi != NO_PIDSTAT; psi = bgpids.storage[psi].bucket_next)
|
||
|
! {
|
||
|
! if (bgpids.storage[psi].pid == pid)
|
||
|
! return (bgpids.storage[psi].status);
|
||
|
! if (orig_psi == bgpids.storage[psi].bucket_next) /* catch reported bug */
|
||
|
! {
|
||
|
! internal_warning ("bgp_search: LOOP: psi (%d) == storage[psi].bucket_next", psi);
|
||
|
! return -1;
|
||
|
! }
|
||
|
! }
|
||
|
|
||
|
return -1;
|
||
|
*** bash-4.4/patchlevel.h 2016-06-22 14:51:03.000000000 -0400
|
||
|
--- b/patchlevel.h 2016-10-01 11:01:28.000000000 -0400
|
||
|
***************
|
||
|
*** 26,30 ****
|
||
|
looks for to find the patch level (for the sccs version string). */
|
||
|
|
||
|
! #define PATCHLEVEL 19
|
||
|
|
||
|
#endif /* _PATCHLEVEL_H_ */
|
||
|
--- b/26,30 ----
|
||
|
looks for to find the patch level (for the sccs version string). */
|
||
|
|
||
|
! #define PATCHLEVEL 20
|
||
|
|
||
|
#endif /* _PATCHLEVEL_H_ */
|