| 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_ */ |