On Mon, 5 Dec 2011, Camiel Dobbelaar wrote:
> > Another might be to inhibit the processing of IMSG_HOST_STATUS only until
> > the configuration has been completed (that is after receiving 
> > IMSG_CFG_DONE):
> 
> I'm going to try this one.  I'm not sure how bad it is to discard
> messages though.

I tried it, and it does not work correctly.  Because the imsg is dropped 
while the process is marked inactive, you get desynchronized and this code 
for example still breaks:

                if (host->check_cnt != st.check_cnt) {
                        log_debug("%s: host %d => %d", __func__,
                            host->conf.id, host->up);
                        fatalx("pfe_dispatch_hce: desynchronized");
                }

Maybe that can be fixed, if we can assume that it's not bad to drop 
some status messages once in a while.

I tried another approach below: only start the processes if _all_ of them 
have loaded the config.  This should fix the configuration race after 
startup completely.

There's still a race while reloading though.  Some processes might still 
be active with an old config, while others may be busy purging their old 
config before loading the new one.  The right way would be to pauze all 
the processes first.  But I'd say that's a seperate problem.  :-)

--
Cam


Index: hce.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/hce.c,v
retrieving revision 1.61
diff -u -p -r1.61 hce.c
--- hce.c       12 Nov 2011 19:36:17 -0000      1.61
+++ hce.c       2 Jan 2012 13:57:40 -0000
@@ -355,6 +355,8 @@ hce_dispatch_parent(int fd, struct privs
                break;
        case IMSG_CFG_DONE:
                config_getcfg(env, imsg);
+               break;
+       case IMSG_CTL_START:
                hce_setup_events();
                break;
        case IMSG_CTL_RESET:
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.159
diff -u -p -r1.159 parse.y
--- parse.y     21 Sep 2011 18:45:40 -0000      1.159
+++ parse.y     2 Jan 2012 13:57:40 -0000
@@ -2280,9 +2280,6 @@ load_config(const char *filename, struct
                errors++;
        }
 
-       if (TAILQ_EMPTY(conf->sc_relays))
-               conf->sc_prefork_relay = 0;
-
        /* Cleanup relay list to inherit */
        while ((rlay = TAILQ_FIRST(&relays)) != NULL) {
                TAILQ_REMOVE(&relays, rlay, rl_entry);
Index: pfe.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/pfe.c,v
retrieving revision 1.71
diff -u -p -r1.71 pfe.c
--- pfe.c       12 Nov 2011 19:36:17 -0000      1.71
+++ pfe.c       2 Jan 2012 13:57:40 -0000
@@ -203,6 +203,8 @@ pfe_dispatch_parent(int fd, struct privs
                config_getcfg(env, imsg);
                init_filter(env, imsg->fd);
                init_tables(env);
+               break;
+       case IMSG_CTL_START:
                pfe_setup_events();
                pfe_sync();
                break;
Index: relay.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.143
diff -u -p -r1.143 relay.c
--- relay.c     21 Sep 2011 18:45:40 -0000      1.143
+++ relay.c     2 Jan 2012 13:57:40 -0000
@@ -2577,6 +2577,8 @@ relay_dispatch_parent(int fd, struct pri
                break;
        case IMSG_CFG_DONE:
                config_getcfg(env, imsg);
+               break;
+       case IMSG_CTL_START:
                relay_launch();
                break;
        case IMSG_CTL_RESET:
Index: relayd.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v
retrieving revision 1.104
diff -u -p -r1.104 relayd.c
--- relayd.c    4 Sep 2011 20:26:58 -0000       1.104
+++ relayd.c    2 Jan 2012 13:57:40 -0000
@@ -49,6 +49,7 @@
 __dead void     usage(void);
 
 int             parent_configure(struct relayd *);
+void            parent_configure_done(struct relayd *);
 void            parent_reload(struct relayd *, u_int, const char *);
 void            parent_sig_handler(int, short, void *);
 void            parent_shutdown(struct relayd *);
@@ -292,6 +293,9 @@ parent_configure(struct relayd *env)
        TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
                config_setrelay(env, rlay);
 
+       /* HCE, PFE and the preforked relays need to reload their config. */
+       env->sc_reload = 2 + env->sc_prefork_relay;
+
        for (id = 0; id < PROC_MAX; id++) {
                if (id == privsep_process)
                        continue;
@@ -308,7 +312,6 @@ parent_configure(struct relayd *env)
                } else
                        s = -1;
 
-               env->sc_reload++;
                proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, s,
                    &cf, sizeof(cf));
        }
@@ -354,6 +357,28 @@ parent_reload(struct relayd *env, u_int 
 }
 
 void
+parent_configure_done(struct relayd *env)
+{
+       int      id;
+
+       if (env->sc_reload == 0) {
+               log_warnx("%s: configuration already finished", __func__);
+               return;
+       }
+
+       env->sc_reload--;
+       if (env->sc_reload == 0) {
+               for (id = 0; id < PROC_MAX; id++) {
+                       if (id == privsep_process)
+                               continue;
+
+                       proc_compose_imsg(env->sc_ps, id, -1, IMSG_CTL_START,
+                           -1, NULL, 0);
+               }
+       }
+}
+
+void
 parent_shutdown(struct relayd *env)
 {
        config_purge(env, CONFIG_ALL);
@@ -408,8 +433,7 @@ parent_dispatch_pfe(int fd, struct privs
                parent_shutdown(env);
                break;
        case IMSG_CFG_DONE:
-               if (env->sc_reload)
-                       env->sc_reload--;
+               parent_configure_done(env);
                break;
        default:
                return (-1);
@@ -437,8 +461,7 @@ parent_dispatch_hce(int fd, struct privs
                (void)snmp_setsock(env, p->p_id);
                break;
        case IMSG_CFG_DONE:
-               if (env->sc_reload)
-                       env->sc_reload--;
+               parent_configure_done(env);
                break;
        default:
                return (-1);
@@ -476,8 +499,7 @@ parent_dispatch_relay(int fd, struct pri
                    IMSG_BINDANY, s, &bnd.bnd_id, sizeof(bnd.bnd_id));
                break;
        case IMSG_CFG_DONE:
-               if (env->sc_reload)
-                       env->sc_reload--;
+               parent_configure_done(env);
                break;
        default:
                return (-1);
Index: relayd.h
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.151
diff -u -p -r1.151 relayd.h
--- relayd.h    4 Sep 2011 20:26:58 -0000       1.151
+++ relayd.h    2 Jan 2012 13:57:40 -0000
@@ -742,6 +742,7 @@ enum imsg_type {
        IMSG_CTL_HOST_ENABLE,
        IMSG_CTL_HOST_DISABLE,
        IMSG_CTL_SHUTDOWN,
+       IMSG_CTL_START,
        IMSG_CTL_RELOAD,
        IMSG_CTL_RESET,
        IMSG_CTL_POLL,

Reply via email to