bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] xargs with large (or zero) max-procs


From: Marc Aurele La France
Subject: [PATCH] xargs with large (or zero) max-procs
Date: Wed, 26 Dec 2007 15:51:15 -0700 (MST)

Hi.

The -p1 patch below causes `xargs` to reap its zombied children before
attempting to fork() another child process.  This is intended to make it
more difficult for a user to fill up the process table, potentially
causing other system services to fail.

This is keyed on whether or not <sys/wait.h> #define's WNOHANG, but you
might want to key off of the existence of waitpid(), using the automangle
suite.  I am submitting this in its current form given that waitpid() is
just about as old as wait(), older than wait3() and wait4() even, and that
there is no point in WNOHANG without waitpid() or vice-versa.

Marc.

+----------------------------------+----------------------------------+
|  Marc Aurele La France           |  work:   1-780-492-9310          |
|  Academic Information and        |  fax:    1-780-492-1729          |
|    Communications Technologies   |  email:  address@hidden         |
|  352 General Services Building   +----------------------------------+
|  University of Alberta           |                                  |
|  Edmonton, Alberta               |    Standard disclaimers apply    |
|  T6G 2H1                         |                                  |
|  CANADA                          |                                  |
+----------------------------------+----------------------------------+
XFree86 developer and VP.  ATI driver and X server internals.

diff -adENpRru findutils-4.2.31/xargs/xargs.c devel/xargs/xargs.c
--- findutils-4.2.31/xargs/xargs.c      Thu Mar  1 17:14:25 2007
+++ devel/xargs/xargs.c Wed Dec 26 16:42:11 2007
@@ -267,7 +267,7 @@ static boolean print_args PARAMS ((boole
 static int xargs_do_exec (const struct buildcmd_control *cl, struct 
buildcmd_state *state);
 static void exec_if_possible PARAMS ((void));
 static void add_proc PARAMS ((pid_t pid));
-static void wait_for_proc PARAMS ((boolean all));
+static void wait_for_proc PARAMS ((int all));
 static void wait_for_proc_all PARAMS ((void));
 static long parse_num PARAMS ((char *str, int option, long min, long max, int 
fatal));
 static void usage PARAMS ((FILE * stream));
@@ -1013,13 +1013,15 @@ xargs_do_exec (const struct buildcmd_con
   if (!query_before_executing || print_args (true))
     {
       if (proc_max && procs_executing >= proc_max)
-       wait_for_proc (false);
+       wait_for_proc (0);
+      else
+       wait_for_proc(-1);
       if (!query_before_executing && print_command)
        print_args (false);
       /* If we run out of processes, wait for a child to return and
          try again.  */
       while ((child = fork ()) < 0 && errno == EAGAIN && procs_executing)
-       wait_for_proc (false);
+       wait_for_proc (0);
       switch (child)
        {
        case -1:
@@ -1081,13 +1083,25 @@ add_proc (pid_t pid)
   procs_executed++;
 }
 
-/* If ALL is true, wait for all child processes to finish;
-   otherwise, wait for one child process to finish.
+/* If ALL is positive, wait for all child processes to finish;
+   if ALL is negative, only reap children that might have finished by now;
+   otherwise, wait for at least one child process to finish.
    Remove the processes that finish from the list of executing processes.  */
 
 static void
-wait_for_proc (boolean all)
+wait_for_proc (int all)
 {
+
+#ifdef WNOHANG
+  int nosuspend = 0;
+
+  if (all < 0)
+    nosuspend = WNOHANG;
+#else
+  if (all < 0)
+    return;
+#endif
+
   while (procs_executing)
     {
       int i, status;
@@ -1096,10 +1110,19 @@ wait_for_proc (boolean all)
        {
          pid_t pid;
 
+#ifdef WNOHANG
+         while ((pid = waitpid ((pid_t) -1, &status, nosuspend)) == (pid_t) -1)
+#else
          while ((pid = wait (&status)) == (pid_t) -1)
+#endif
            if (errno != EINTR)
              error (1, errno, _("error waiting for child process"));
 
+#ifdef WNOHANG
+         if (pid == 0)         /* Can only occur with WNOHANG */
+           return;
+#endif
+
          /* Find the entry in `pids' for the child process
             that exited.  */
          for (i = 0; i < pids_alloc && pid != pids[i]; i++)
@@ -1122,8 +1145,13 @@ wait_for_proc (boolean all)
       if (WEXITSTATUS (status) != 0)
        child_error = 123;
 
+#ifdef WNOHANG
+      if (all <= 0)
+       nosuspend = WNOHANG;
+#else
       if (!all)
-       break;
+       return;
+#endif
     }
 }
 
@@ -1138,7 +1166,7 @@ wait_for_proc_all (void)
     return;
 
   waiting = true;
-  wait_for_proc (true);
+  wait_for_proc (1);
   waiting = false;
   
   if (original_exit_value != child_error)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]