Patch from Paul Haas:
authorMartin Pool <mbp@samba.org>
Wed, 20 Mar 2002 01:09:49 +0000 (01:09 +0000)
committerMartin Pool <mbp@samba.org>
Wed, 20 Mar 2002 01:09:49 +0000 (01:09 +0000)
    * Fix situation where failure to fork (e.g. because out of process
      slots) would cause rsync to kill all processes owned by the
      current user.  Yes, really!  (Paul Haas, Martin Pool)

Also, add a little more documentation and paranoia to make sure we
never call kill(2) with a negative pid.

NEWS
util.c

diff --git a/NEWS b/NEWS
index 3a22226..ef198c4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,10 +10,14 @@ rsync changes since last release
 
   BUG FIXES:
 
+    * Fix situation where failure to fork (e.g. because out of process
+      slots) would cause rsync to kill all processes owned by the
+      current user.  Yes, really!  (Paul Haas, Martin Pool)
+
     * Fix test suite on Solaris.  (Jos Backus)
 
     * Fix minor memory leak in socket code.  (Dave Dykstra, Martin
       Pool.)
 
     * Fix --whole-file problem that caused it to be the default even
-      for remote connections.  (Frank Schulz)
+      for remote connections.  (Martin Pool, Frank Schulz)
diff --git a/util.c b/util.c
index c1e0471..245f3b2 100644 (file)
--- a/util.c
+++ b/util.c
@@ -478,27 +478,47 @@ int robust_rename(char *from, char *to)
 static pid_t all_pids[10];
 static int num_pids;
 
-/* fork and record the pid of the child */
+/** Fork and record the pid of the child. **/
 pid_t do_fork(void)
 {
        pid_t newpid = fork();
        
-       if (newpid) {
+       if (newpid != 0  &&  newpid != -1) {
                all_pids[num_pids++] = newpid;
        }
        return newpid;
 }
 
-/* kill all children */
+/**
+ * Kill all children.
+ *
+ * @todo It would be kind of nice to make sure that they are actually
+ * all our children before we kill them, because their pids may have
+ * been recycled by some other process.  Perhaps when we wait for a
+ * child, we should remove it from this array.  Alternatively we could
+ * perhaps use process groups, but I think that would not work on
+ * ancient Unix versions that don't support them.
+ **/
 void kill_all(int sig)
 {
        int i;
-       for (i=0;i<num_pids;i++) {
-               if (all_pids[i] != getpid())
-                       kill(all_pids[i], sig);
+
+       for (i = 0; i < num_pids; i++) {
+               /* Let's just be a little careful where we
+                * point that gun, hey?  See kill(2) for the
+                * magic caused by negative values. */
+               pid_t p = all_pids[i];
+
+               if (p == getpid())
+                       continue;
+               if (p <= 0)
+                       continue;
+
+               kill(p, sig);
        }
 }
 
+
 /* turn a user name into a uid */
 int name_to_uid(char *name, uid_t *uid)
 {