]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
saved background process status hash table loop fixes
authorChet Ramey <chet.ramey@case.edu>
Fri, 1 Jun 2018 14:19:56 +0000 (10:19 -0400)
committerChet Ramey <chet.ramey@case.edu>
Fri, 1 Jun 2018 14:19:56 +0000 (10:19 -0400)
jobs.c
patchlevel.h

diff --git a/jobs.c b/jobs.c
index fc966036663935156efae44d1909f3670fd9e52a..2684632df99cafbd6f41170345358b78c7762eff 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -812,8 +812,22 @@ bgp_add (pid, status)
   ps_index_t *bucket, psi;
   struct pidstat *ps;
 
-  bucket = pshash_getbucket (pid);
-  psi = bgp_getindex ();
+  /* 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];
 
   ps->pid = pid;
@@ -841,32 +855,47 @@ pshash_delindex (psi)
      ps_index_t psi;
 {
   struct pidstat *ps;
+  ps_index_t *bucket;
 
   ps = &bgpids.storage[psi];
   if (ps->pid == NO_PID)
     return;
 
-  if (ps->bucket_next != NO_PID)
+  if (ps->bucket_next != NO_PIDSTAT)
     bgpids.storage[ps->bucket_next].bucket_prev = ps->bucket_prev;
-  if (ps->bucket_prev != NO_PID)
+  if (ps->bucket_prev != NO_PIDSTAT)
     bgpids.storage[ps->bucket_prev].bucket_next = ps->bucket_next;
   else
-    *(pshash_getbucket (ps->pid)) = ps->bucket_next;
+    {
+      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;
 }
 
 static int
 bgp_delete (pid)
      pid_t pid;
 {
-  ps_index_t psi;
+  ps_index_t psi, orig_psi;
 
   if (bgpids.storage == 0 || bgpids.nalloc == 0 || bgpids.npid == 0)
     return 0;
 
   /* 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;
+  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)
     return 0;          /* not found */
@@ -904,15 +933,22 @@ static int
 bgp_search (pid)
      pid_t pid;
 {
-  ps_index_t psi;
+  ps_index_t psi, orig_psi;
 
   if (bgpids.storage == 0 || bgpids.nalloc == 0 || bgpids.npid == 0)
     return -1;
 
   /* 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);
+  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;
 }
index a711c4957721d613da77578c0073e39952a535ab..4a65dc0ff02b0f07eac616d727e6db973d330360 100644 (file)
@@ -25,6 +25,6 @@
    regexp `^#define[   ]*PATCHLEVEL', since that's what support/mkversion.sh
    looks for to find the patch level (for the sccs version string). */
 
-#define PATCHLEVEL 19
+#define PATCHLEVEL 20
 
 #endif /* _PATCHLEVEL_H_ */