diff --git a/sbin/hastd/control.c b/sbin/hastd/control.c index eab7a9e1d57b..87fa42abbf82 100644 --- a/sbin/hastd/control.c +++ b/sbin/hastd/control.c @@ -411,7 +411,6 @@ ctrl_thread(void *arg) nv_free(nvin); continue; } - nv_free(nvin); nvout = nv_alloc(); switch (cmd) { case HASTCTL_STATUS: @@ -433,11 +432,23 @@ ctrl_thread(void *arg) nv_add_uint32(nvout, (uint32_t)0, "keepdirty"); nv_add_uint64(nvout, (uint64_t)0, "dirty"); } + nv_add_int16(nvout, 0, "error"); + break; + case HASTCTL_RELOAD: + /* + * When parent receives SIGHUP and discovers that + * something related to us has changes, it sends reload + * message to us. + */ + assert(res->hr_role == HAST_ROLE_PRIMARY); + primary_config_reload(res, nvin); + nv_add_int16(nvout, 0, "error"); break; default: nv_add_int16(nvout, EINVAL, "error"); break; } + nv_free(nvin); if (nv_error(nvout) != 0) { pjdlog_error("Unable to create answer on control message."); nv_free(nvout); diff --git a/sbin/hastd/control.h b/sbin/hastd/control.h index 582617d21e18..ed8e4ffdfb05 100644 --- a/sbin/hastd/control.h +++ b/sbin/hastd/control.h @@ -34,6 +34,7 @@ #define HASTCTL_SET_ROLE 1 #define HASTCTL_STATUS 2 +#define HASTCTL_RELOAD 3 struct hastd_config; struct hast_resource; diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index ea9821e1ab5d..30478cad60ab 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -204,6 +204,45 @@ resource_needs_reload(const struct hast_resource *res0, return (false); } +static void +resource_reload(const struct hast_resource *res) +{ + struct nv *nvin, *nvout; + int error; + + assert(res->hr_role == HAST_ROLE_PRIMARY); + + nvout = nv_alloc(); + nv_add_uint8(nvout, HASTCTL_RELOAD, "cmd"); + nv_add_string(nvout, res->hr_remoteaddr, "remoteaddr"); + nv_add_int32(nvout, (int32_t)res->hr_replication, "replication"); + nv_add_int32(nvout, (int32_t)res->hr_timeout, "timeout"); + nv_add_string(nvout, res->hr_exec, "exec"); + if (nv_error(nvout) != 0) { + nv_free(nvout); + pjdlog_error("Unable to allocate header for reload message."); + return; + } + if (hast_proto_send(res, res->hr_ctrl, nvout, NULL, 0) < 0) { + pjdlog_errno(LOG_ERR, "Unable to send reload message"); + nv_free(nvout); + return; + } + nv_free(nvout); + + /* Receive response. */ + if (hast_proto_recv_hdr(res->hr_ctrl, &nvin) < 0) { + pjdlog_errno(LOG_ERR, "Unable to receive reload reply"); + return; + } + error = nv_get_int16(nvin, "error"); + nv_free(nvin); + if (error != 0) { + pjdlog_common(LOG_ERR, 0, error, "Reload failed"); + return; + } +} + static void hastd_reload(void) { @@ -338,13 +377,8 @@ hastd_reload(void) cres->hr_timeout = nres->hr_timeout; strlcpy(cres->hr_exec, nres->hr_exec, sizeof(cres->hr_exec)); - if (cres->hr_workerpid != 0) { - if (kill(cres->hr_workerpid, SIGHUP) < 0) { - pjdlog_errno(LOG_WARNING, - "Unable to send SIGHUP to worker process %u", - (unsigned int)cres->hr_workerpid); - } - } + if (cres->hr_workerpid != 0) + resource_reload(cres); } } diff --git a/sbin/hastd/hastd.h b/sbin/hastd/hastd.h index 0186e81e0e8e..1157f926e8d9 100644 --- a/sbin/hastd/hastd.h +++ b/sbin/hastd/hastd.h @@ -46,4 +46,6 @@ extern struct pidfh *pfh; void hastd_primary(struct hast_resource *res); void hastd_secondary(struct hast_resource *res, struct nv *nvin); +void primary_config_reload(struct hast_resource *res, struct nv *nv); + #endif /* !_HASTD_H_ */ diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index e1083975379b..a4cd1725537c 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -836,6 +836,7 @@ hastd_primary(struct hast_resource *res) init_local(res); init_ggate(res); init_environment(res); + /* * Create the guard thread first, so we can handle signals from the * very begining. @@ -1844,47 +1845,32 @@ sync_thread(void *arg __unused) return (NULL); } -static void -config_reload(void) +void +primary_config_reload(struct hast_resource *res, struct nv *nv) { - struct hastd_config *newcfg; - struct hast_resource *res; unsigned int ii, ncomps; - int modified; + int modified, vint; + const char *vstr; pjdlog_info("Reloading configuration..."); + assert(res->hr_role == HAST_ROLE_PRIMARY); + assert(gres == res); + nv_assert(nv, "remoteaddr"); + nv_assert(nv, "replication"); + nv_assert(nv, "timeout"); + nv_assert(nv, "exec"); + ncomps = HAST_NCOMPONENTS; - newcfg = yy_config_parse(cfgpath, false); - if (newcfg == NULL) - goto failed; - - TAILQ_FOREACH(res, &newcfg->hc_resources, hr_next) { - if (strcmp(res->hr_name, gres->hr_name) == 0) - break; - } - /* - * If resource was removed from the configuration file, resource - * name, provider name or path to local component was modified we - * shouldn't be here. This means that someone modified configuration - * file and send SIGHUP to us instead of main hastd process. - * Log advice and ignore the signal. - */ - if (res == NULL || strcmp(gres->hr_name, res->hr_name) != 0 || - strcmp(gres->hr_provname, res->hr_provname) != 0 || - strcmp(gres->hr_localpath, res->hr_localpath) != 0) { - pjdlog_warning("To reload configuration send SIGHUP to the main hastd process (pid %u).", - (unsigned int)getppid()); - goto failed; - } - #define MODIFIED_REMOTEADDR 0x1 #define MODIFIED_REPLICATION 0x2 #define MODIFIED_TIMEOUT 0x4 #define MODIFIED_EXEC 0x8 modified = 0; - if (strcmp(gres->hr_remoteaddr, res->hr_remoteaddr) != 0) { + + vstr = nv_get_string(nv, "remoteaddr"); + if (strcmp(gres->hr_remoteaddr, vstr) != 0) { /* * Don't copy res->hr_remoteaddr to gres just yet. * We want remote_close() to log disconnect from the old @@ -1892,18 +1878,22 @@ config_reload(void) */ modified |= MODIFIED_REMOTEADDR; } - if (gres->hr_replication != res->hr_replication) { - gres->hr_replication = res->hr_replication; + vint = nv_get_int32(nv, "replication"); + if (gres->hr_replication != vint) { + gres->hr_replication = vint; modified |= MODIFIED_REPLICATION; } - if (gres->hr_timeout != res->hr_timeout) { - gres->hr_timeout = res->hr_timeout; + vint = nv_get_int32(nv, "timeout"); + if (gres->hr_timeout != vint) { + gres->hr_timeout = vint; modified |= MODIFIED_TIMEOUT; } - if (strcmp(gres->hr_exec, res->hr_exec) != 0) { - strlcpy(gres->hr_exec, res->hr_exec, sizeof(gres->hr_exec)); + vstr = nv_get_string(nv, "exec"); + if (strcmp(gres->hr_exec, vstr) != 0) { + strlcpy(gres->hr_exec, vstr, sizeof(gres->hr_exec)); modified |= MODIFIED_EXEC; } + /* * If only timeout was modified we only need to change it without * reconnecting. @@ -1937,7 +1927,8 @@ config_reload(void) remote_close(gres, ii); } if (modified & MODIFIED_REMOTEADDR) { - strlcpy(gres->hr_remoteaddr, res->hr_remoteaddr, + vstr = nv_get_string(nv, "remoteaddr"); + strlcpy(gres->hr_remoteaddr, vstr, sizeof(gres->hr_remoteaddr)); } } @@ -1947,16 +1938,6 @@ config_reload(void) #undef MODIFIED_EXEC pjdlog_info("Configuration reloaded successfully."); - return; -failed: - if (newcfg != NULL) { - if (newcfg->hc_controlconn != NULL) - proto_close(newcfg->hc_controlconn); - if (newcfg->hc_listenconn != NULL) - proto_close(newcfg->hc_listenconn); - yy_config_free(newcfg); - } - pjdlog_warning("Configuration not reloaded."); } static void @@ -2032,7 +2013,6 @@ guard_thread(void *arg) lastcheck = time(NULL); PJDLOG_VERIFY(sigemptyset(&mask) == 0); - PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); @@ -2042,9 +2022,6 @@ guard_thread(void *arg) for (;;) { switch (signo) { - case SIGHUP: - config_reload(); - break; case SIGINT: case SIGTERM: sigexit_received = true;