mirror of
https://github.com/pygos/init.git
synced 2024-12-22 07:10:49 +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 <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -55,6 +56,8 @@ static int cmd_disable(int argc, char **argv)
|
|||
goto out;
|
||||
}
|
||||
|
||||
kill(1, SIGHUP);
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
out:
|
||||
free(linkname);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -60,6 +61,8 @@ static int cmd_enable(int argc, char **argv)
|
|||
goto out;
|
||||
}
|
||||
|
||||
kill(1, SIGHUP);
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
out:
|
||||
free(linkname);
|
||||
|
|
|
@ -68,6 +68,8 @@ void supervisor_init(void);
|
|||
|
||||
bool supervisor_process_queues(void);
|
||||
|
||||
void supervisor_reload_config(void);
|
||||
|
||||
void supervisor_answer_status_request(int fd, const void *dest_addr,
|
||||
size_t addrlen, E_SERVICE_STATE filter);
|
||||
|
||||
|
|
|
@ -30,6 +30,9 @@ static void handle_signal(void)
|
|||
case SIGINT:
|
||||
supervisor_set_target(TGT_REBOOT);
|
||||
break;
|
||||
case SIGHUP:
|
||||
supervisor_reload_config();
|
||||
break;
|
||||
case SIGUSR1:
|
||||
if (sockfd >= 0) {
|
||||
close(sockfd);
|
||||
|
|
|
@ -19,6 +19,7 @@ int sigsetup(void)
|
|||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigaddset(&mask, SIGHUP);
|
||||
|
||||
sfd = signalfd(-1, &mask, SFD_CLOEXEC);
|
||||
if (sfd == -1) {
|
||||
|
|
|
@ -13,6 +13,46 @@ static service_t *failed = NULL;
|
|||
static int singleshot = 0;
|
||||
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)
|
||||
{
|
||||
if (svc->id < 1)
|
||||
|
@ -145,6 +185,45 @@ void supervisor_init(void)
|
|||
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)
|
||||
{
|
||||
service_t *svc;
|
||||
|
|
Loading…
Reference in a new issue