Author: kevans
Date: Wed Jan  1 04:22:04 2020
New Revision: 356247
URL: https://svnweb.freebsd.org/changeset/base/356247

Log:
  inetd: track all child pids, regardless of maxchild spec
  
  Currently, child pids are only tracked if maxchildren is specified. As a
  consequence, without a maxchild limit we do not get a notice in syslog on
  children aborting abnormally. This turns out to be a great debugging aide at
  times.
  
  Children are now tracked in a LIST; the management interface is decidedly
  less painful when there's no upper bound on the number of entries we may
  have at the cost of one small allocation per connection.
  
  PR:           70335

Modified:
  head/usr.sbin/inetd/inetd.c
  head/usr.sbin/inetd/inetd.h

Modified: head/usr.sbin/inetd/inetd.c
==============================================================================
--- head/usr.sbin/inetd/inetd.c Wed Jan  1 03:59:54 2020        (r356246)
+++ head/usr.sbin/inetd/inetd.c Wed Jan  1 04:22:04 2020        (r356247)
@@ -922,8 +922,8 @@ flag_signal(int signo)
 static void
 addchild(struct servtab *sep, pid_t pid)
 {
-       if (sep->se_maxchild <= 0)
-               return;
+       struct stabchild *sc;
+
 #ifdef SANITY_CHECK
        if (SERVTAB_EXCEEDS_LIMIT(sep)) {
                syslog(LOG_ERR, "%s: %d >= %d",
@@ -931,7 +931,15 @@ addchild(struct servtab *sep, pid_t pid)
                exit(EX_SOFTWARE);
        }
 #endif
-       sep->se_pids[sep->se_numchild++] = pid;
+       sc = malloc(sizeof(*sc));
+       if (sc == NULL) {
+               syslog(LOG_ERR, "malloc: %m");
+               exit(EX_OSERR);
+       }
+       memset(sc, 0, sizeof(*sc));
+       sc->sc_pid = pid;
+       LIST_INSERT_HEAD(&sep->se_children, sc, sc_link);
+       ++sep->se_numchild;
        if (SERVTAB_AT_LIMIT(sep))
                disable(sep);
 }
@@ -939,8 +947,9 @@ addchild(struct servtab *sep, pid_t pid)
 static void
 reapchild(void)
 {
-       int k, status;
+       int status;
        pid_t pid;
+       struct stabchild *sc;
        struct servtab *sep;
 
        for (;;) {
@@ -953,14 +962,17 @@ reapchild(void)
                            WIFEXITED(status) ? WEXITSTATUS(status)
                                : WTERMSIG(status));
                for (sep = servtab; sep; sep = sep->se_next) {
-                       for (k = 0; k < sep->se_numchild; k++)
-                               if (sep->se_pids[k] == pid)
+                       LIST_FOREACH(sc, &sep->se_children, sc_link) {
+                               if (sc->sc_pid == pid)
                                        break;
-                       if (k == sep->se_numchild)
+                       }
+                       if (sc == NULL)
                                continue;
                        if (SERVTAB_AT_LIMIT(sep))
                                enable(sep);
-                       sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
+                       LIST_REMOVE(sc, sc_link);
+                       free(sc);
+                       --sep->se_numchild;
                        if (WIFSIGNALED(status) || WEXITSTATUS(status))
                                syslog(LOG_WARNING,
                                    "%s[%d]: exited, %s %u",
@@ -1032,18 +1044,14 @@ config(void)
                                        sep->se_nomapped = new->se_nomapped;
                                sep->se_reset = 1;
                        }
-                       /* copy over outstanding child pids */
-                       if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
-                               new->se_numchild = sep->se_numchild;
-                               if (new->se_numchild > new->se_maxchild)
-                                       new->se_numchild = new->se_maxchild;
-                               memcpy(new->se_pids, sep->se_pids,
-                                   new->se_numchild * sizeof(*new->se_pids));
-                       }
-                       SWAP(pid_t *, sep->se_pids, new->se_pids);
-                       sep->se_maxchild = new->se_maxchild;
-                       sep->se_numchild = new->se_numchild;
+
+                       /*
+                        * The children tracked remain; we want numchild to
+                        * still reflect how many jobs are running so we don't
+                        * throw off our accounting.
+                        */
                        sep->se_maxcpm = new->se_maxcpm;
+                       sep->se_maxchild = new->se_maxchild;
                        resize_conn(sep, new->se_maxperip);
                        sep->se_maxperip = new->se_maxperip;
                        sep->se_bi = new->se_bi;
@@ -1949,13 +1957,7 @@ more:
                else
                        sep->se_maxchild = 1;
        }
-       if (sep->se_maxchild > 0) {
-               sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
-               if (sep->se_pids == NULL) {
-                       syslog(LOG_ERR, "malloc: %m");
-                       exit(EX_OSERR);
-               }
-       }
+       LIST_INIT(&sep->se_children);
        argc = 0;
        for (arg = skip(&cp); cp; arg = skip(&cp))
                if (argc < MAXARGV) {
@@ -1980,6 +1982,7 @@ more:
 static void
 freeconfig(struct servtab *cp)
 {
+       struct stabchild *sc;
        int i;
 
        if (cp->se_service)
@@ -1996,8 +1999,11 @@ freeconfig(struct servtab *cp)
 #endif
        if (cp->se_server)
                free(cp->se_server);
-       if (cp->se_pids)
-               free(cp->se_pids);
+       while (!LIST_EMPTY(&cp->se_children)) {
+               sc = LIST_FIRST(&cp->se_children);
+               LIST_REMOVE(sc, sc_link);
+               free(sc);
+       }
        for (i = 0; i < MAXARGV; i++)
                if (cp->se_argv[i])
                        free(cp->se_argv[i]);

Modified: head/usr.sbin/inetd/inetd.h
==============================================================================
--- head/usr.sbin/inetd/inetd.h Wed Jan  1 03:59:54 2020        (r356246)
+++ head/usr.sbin/inetd/inetd.h Wed Jan  1 04:22:04 2020        (r356247)
@@ -66,6 +66,11 @@ struct conninfo {
 
 #define PERIPSIZE      256
 
+struct stabchild {
+       LIST_ENTRY(stabchild)   sc_link;
+       pid_t                   sc_pid;
+};
+
 struct servtab {
        char    *se_service;            /* name of service */
        int     se_socktype;            /* type of socket to use */
@@ -74,7 +79,6 @@ struct        servtab {
        int     se_maxchild;            /* max number of children */
        int     se_maxcpm;              /* max connects per IP per minute */
        int     se_numchild;            /* current number of children */
-       pid_t   *se_pids;               /* array of child pids */
        char    *se_user;               /* user name to run as */
        char    *se_group;              /* group name to run as */
 #ifdef  LOGIN_CAP
@@ -119,6 +123,7 @@ struct      servtab {
        } se_flags;
        int     se_maxperip;            /* max number of children per src */
        LIST_HEAD(, conninfo) se_conn[PERIPSIZE];
+       LIST_HEAD(, stabchild) se_children;
 };
 
 #define        se_nomapped             se_flags.se_nomapped
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to