mirror of
https://github.com/pygos/init.git
synced 2024-11-22 03:09:46 +01:00
Add service configuration reloading
This commit add the ability to initd to reload the service configuration while running. The new configuration is merged with the existing one as follows: For each target: - If the existing service list is not NULL, we have not started that target yet. Simply replace it with the new list. - If it is NULL, the services have already been started. - First, remove all entries for services in that target that no loner exist (except from the 'running' list). - Second, add new services that we don't have yet. Treat them as recently diseased and let the user start them manualy. Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
parent
6fa0393be4
commit
028394b8a5
6 changed files with 91 additions and 0 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
@ -55,6 +56,8 @@ static int cmd_disable(int argc, char **argv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kill(1, SIGHUP);
|
||||||
|
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
out:
|
out:
|
||||||
free(linkname);
|
free(linkname);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
@ -60,6 +61,8 @@ static int cmd_enable(int argc, char **argv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kill(1, SIGHUP);
|
||||||
|
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
out:
|
out:
|
||||||
free(linkname);
|
free(linkname);
|
||||||
|
|
|
@ -68,6 +68,8 @@ void supervisor_init(void);
|
||||||
|
|
||||||
bool supervisor_process_queues(void);
|
bool supervisor_process_queues(void);
|
||||||
|
|
||||||
|
void supervisor_reload_config(void);
|
||||||
|
|
||||||
void supervisor_answer_status_request(int fd, const void *dest_addr,
|
void supervisor_answer_status_request(int fd, const void *dest_addr,
|
||||||
size_t addrlen, E_SERVICE_STATE filter);
|
size_t addrlen, E_SERVICE_STATE filter);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ static void handle_signal(void)
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
supervisor_set_target(TGT_REBOOT);
|
supervisor_set_target(TGT_REBOOT);
|
||||||
break;
|
break;
|
||||||
|
case SIGHUP:
|
||||||
|
supervisor_reload_config();
|
||||||
|
break;
|
||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
if (sockfd >= 0) {
|
if (sockfd >= 0) {
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
|
|
|
@ -19,6 +19,7 @@ int sigsetup(void)
|
||||||
sigaddset(&mask, SIGINT);
|
sigaddset(&mask, SIGINT);
|
||||||
sigaddset(&mask, SIGTERM);
|
sigaddset(&mask, SIGTERM);
|
||||||
sigaddset(&mask, SIGUSR1);
|
sigaddset(&mask, SIGUSR1);
|
||||||
|
sigaddset(&mask, SIGHUP);
|
||||||
|
|
||||||
sfd = signalfd(-1, &mask, SFD_CLOEXEC);
|
sfd = signalfd(-1, &mask, SFD_CLOEXEC);
|
||||||
if (sfd == -1) {
|
if (sfd == -1) {
|
||||||
|
|
|
@ -13,6 +13,46 @@ static service_t *failed = NULL;
|
||||||
static int singleshot = 0;
|
static int singleshot = 0;
|
||||||
static bool waiting = false;
|
static bool waiting = false;
|
||||||
|
|
||||||
|
static bool find_service(service_t *list, service_t *svc)
|
||||||
|
{
|
||||||
|
while (list != NULL) {
|
||||||
|
if (strcmp(list->fname, svc->fname) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_not_in_list(service_t **current, service_t *list, int tgt)
|
||||||
|
{
|
||||||
|
service_t *it = *current, *prev = NULL;
|
||||||
|
|
||||||
|
while (it != NULL) {
|
||||||
|
if (it->target == tgt && !find_service(list, it)) {
|
||||||
|
if (prev == NULL) {
|
||||||
|
delsvc(it);
|
||||||
|
*current = (*current)->next;
|
||||||
|
it = *current;
|
||||||
|
} else {
|
||||||
|
prev->next = it->next;
|
||||||
|
delsvc(it);
|
||||||
|
it = prev->next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prev = it;
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool have_service(service_t *svc)
|
||||||
|
{
|
||||||
|
return find_service(running, svc) || find_service(terminated, svc) ||
|
||||||
|
find_service(queue, svc) || find_service(completed, svc) ||
|
||||||
|
find_service(failed, svc);
|
||||||
|
}
|
||||||
|
|
||||||
static int start_service(service_t *svc)
|
static int start_service(service_t *svc)
|
||||||
{
|
{
|
||||||
if (svc->id < 1)
|
if (svc->id < 1)
|
||||||
|
@ -145,6 +185,45 @@ void supervisor_init(void)
|
||||||
print_status("reading configuration from " SVCDIR, status, false);
|
print_status("reading configuration from " SVCDIR, status, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void supervisor_reload_config(void)
|
||||||
|
{
|
||||||
|
service_list_t newcfg;
|
||||||
|
service_t *svc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (svcscan(SVCDIR, &newcfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < TGT_MAX; ++i) {
|
||||||
|
if (cfg.targets[i] == NULL) {
|
||||||
|
remove_not_in_list(&queue, newcfg.targets[i], i);
|
||||||
|
remove_not_in_list(&terminated, newcfg.targets[i], i);
|
||||||
|
remove_not_in_list(&completed, newcfg.targets[i], i);
|
||||||
|
remove_not_in_list(&failed, newcfg.targets[i], i);
|
||||||
|
|
||||||
|
while (newcfg.targets[i] != NULL) {
|
||||||
|
svc = newcfg.targets[i];
|
||||||
|
newcfg.targets[i] = svc->next;
|
||||||
|
|
||||||
|
if (have_service(svc)) {
|
||||||
|
delsvc(svc);
|
||||||
|
} else {
|
||||||
|
svc->id = service_id++;
|
||||||
|
svc->status = EXIT_SUCCESS;
|
||||||
|
svc->next = completed;
|
||||||
|
completed = svc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
svc = cfg.targets[i];
|
||||||
|
cfg.targets[i] = newcfg.targets[i];
|
||||||
|
newcfg.targets[i] = svc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
del_svc_list(&newcfg);
|
||||||
|
}
|
||||||
|
|
||||||
bool supervisor_process_queues(void)
|
bool supervisor_process_queues(void)
|
||||||
{
|
{
|
||||||
service_t *svc;
|
service_t *svc;
|
||||||
|
|
Loading…
Reference in a new issue