I am preparing for making 2.5.6pre1 today and decided to submit David
Staples patch with a little rework.  Here's the version I submitted.

- Dave Dykstra


--- main.c~     Thu Aug  1 15:46:59 2002
+++ main.c      Thu Jan  9 12:43:55 2003
@@ -26,6 +26,16 @@
 extern struct stats stats;
 extern int verbose;
 
+/* there's probably never more than at most 2 outstanding child processes,
+ * but set it higher just in case.
+ */
+#define MAXCHILDPROCS 5
+
+struct pid_status {
+       pid_t pid;
+       int   status;
+} pid_stat_table[MAXCHILDPROCS];
+
 static void show_malloc_stats(void);
 
 /****************************************************************************
@@ -33,11 +43,27 @@
 ****************************************************************************/
 void wait_process(pid_t pid, int *status)
 {
-       while (waitpid(pid, status, WNOHANG) == 0) {
+       pid_t waited_pid;
+       int cnt;
+
+       while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
                msleep(20);
                io_flush();
        }
         
+       if ((waited_pid == -1) && (errno == ECHILD)) {
+               /* status of requested child no longer available.
+                * check to see if it was processed by the sigchld_handler.
+                */
+               for (cnt = 0;  cnt < MAXCHILDPROCS; cnt++) {
+                       if (pid == pid_stat_table[cnt].pid) {
+                               *status = pid_stat_table[cnt].status;
+                               pid_stat_table[cnt].pid = 0;
+                               break;
+                       }
+               }
+       }
+
         /* TODO: If the child exited on a signal, then log an
          * appropriate error message.  Perhaps we should also accept a
          * message describing the purpose of the child.  Also indicate
@@ -848,7 +874,24 @@
 
 static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
 #ifdef WNOHANG
-       while (waitpid(-1, NULL, WNOHANG) > 0) ;
+       int cnt, status;
+       pid_t pid;
+       /* An empty waitpid() loop was put here by Tridge and we could never
+        * get him to explain why he put it in, so rather than taking it 
+        * out we're instead saving the child exit statuses for later use.
+        * The waitpid() loop presumably eliminates all possibility of leaving
+        * zombie children, maybe that's why he did it.
+        */
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+                /* save the child's exit status */
+                for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
+                         if (pid_stat_table[cnt].pid == 0) {
+                                  pid_stat_table[cnt].pid = pid;
+                                  pid_stat_table[cnt].status = status;
+                                  break;
+                         }
+                }
+       }
 #endif
 }
 



On Tue, Sep 03, 2002 at 06:29:03PM -0700, jw schultz wrote:
> Subject: Re: [patch] for rsync
> On Tue, Sep 03, 2002 at 05:00:02PM -0700, [EMAIL PROTECTED] wrote:
> > 
> > JW,
> > 
> > I pushed everything to a LINUX box and did the diff again this time with the
> > -bur option.
> > It does look significantly different.  I think I've got below what you are
> > looking for, so I am
> > resending it to [EMAIL PROTECTED]
> > 
> > I'm including two additional people as they have asked for the patch information
> > as well.
> > The diff was performed on main.c (2.5.5 version from rsync.samba.org).  I hope
> > everyone
> > knows that I'm my purpose in providing this information, is so that everyone can
> > critique
> > my code (to make it better) and we can eliminate this problem for everyone.
> > 
> > Dave
> 
> Thank you Dave.  I've been abusing/educating him a bit
> offline so be nice everybody.  He has not only diagnosed the
> bug independantly but has come up with a direction to go
> toward a permanent solution.
> 
> Aside from my dislike of a fixed size array
> my comments are below.
> 
> 
> > -------------------------------------------------------------
> > 
> > --- main.c.orig     Tue Sep  3 16:38:23 2002
> > +++ main.c     Tue Sep  3 16:41:08 2002
> > @@ -27,6 +27,11 @@
> > 
> >  extern int verbose;
> > 
> > +struct pid_status {
> > +    pid_t pid;
> > +    int   status;
> > + } pid_stat_table[10];
> 
> The use of a literal here is bad news.
> Should be a #define CHILD_TABLE_SIZE or whatever.
> Then macro can be used in the loops.
> 
> Question.  Is 10 a good size?  Should it be more?
> I've not dug into the child spawning of rsync.
> 
> > +
> >  static void show_malloc_stats(void);
> > 
> >  /****************************************************************************
> > @@ -34,9 +39,27 @@
> >  ****************************************************************************/
> >  void wait_process(pid_t pid, int *status)
> >  {
> > -    while (waitpid(pid, status, WNOHANG) == 0) {
> > +    pid_t waited_pid;
> > +    int   cnt;
> > +
> > +    while ( 1 ) {
> > +         waited_pid = waitpid(pid, status, WNOHANG);
> > +         if ( waited_pid == 0 ) {
> >           msleep(20);
> >           io_flush();
> > +         } else break;
> > +    }
> > +    if (( waited_pid == -1 ) && ( errno == ECHILD )) {
> > +         /* status of requested child no longer available.  Check */
> > +         /* to see if it was processed by the sigchld_handler.    */
> > +         cnt = 0;
> > +         while ( cnt < 10 ) {
> > +              if ( pid == pid_stat_table[cnt].pid ) {
> > +                   *status = pid_stat_table[cnt].status;
> 
> If we do 'pid_stat_table[cnt].pid = 0' here we'll be able to
> reuse the slots. (if necessary)
> 
> > +                   break;
> > +              }
> > +              cnt++;
> > +         }
> >      }
> > 
> >          /* TODO: If the child exited on a signal, then log an
> > @@ -792,7 +815,22 @@
> > 
> >  static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
> >  #ifdef WNOHANG
> > -    while (waitpid(-1, NULL, WNOHANG) > 0) ;
> > +    int cnt = 0;
> > +    pid_t pid = 0;
> > +    int status = 0;
> > +    while ( 1 ) {
> > +         pid = waitpid(-1, &status, WNOHANG);
> > +         cnt = 0;
> > +         while ( cnt < 10 ) {
> > +              if (pid_stat_table[cnt].pid == 0 ) {
> > +                   pid_stat_table[cnt].pid = pid;
> > +                   pid_stat_table[cnt].status = status;
> > +                   break;
> > +              }
> > +              cnt++;
> > +         }
> > +         if ( pid < 1 ) break;
> 
> If we run off the end of the array (cnt == 10) we should kick out a
> warning or we should resize it.
> 
> > +    };
> >  #endif
> >  }
-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.tuxedo.org/~esr/faqs/smart-questions.html

Reply via email to