Compare commits

..
8 Commits
Author SHA1 Message Date
Joachim Nilsson 8218fff7e5 Update ChangeLog and bump version for v2.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-28 13:59:47 +01:00
Joachim Nilsson 263e23a0df initctl: Support for stop/start services by name:id
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 21:22:05 +01:00
Joachim Nilsson 1f88e1ff8a Refactor svc_status() used by 'initctl show'
Leverage new svc_t states in initctl status/show output.  Also, ensure
different svc_t types have correct start state.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 20:51:04 +01:00
Joachim Nilsson b4ccc8b008 Clean up bootstrap-only tasks when leaving bootstrap 'S' runlevel
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 20:22:24 +01:00
Joachim Nilsson 8df2b7b6e9 service_stop_dynamic(): Skip already stopped and HALT removed services
new postponed stop handling tried to reload already stopped and removed
services.  We should of course skip already stopped services and halt
those that have been removed.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 19:13:39 +01:00
Joachim Nilsson 8073f7cf27 Revert semantic change in 'initctl restart' introduced in 924bf04
This patch reverts the change in behavior introduced in Finit v2.2,
commit 924bf041, where `initctl restart JOB` changed from 'stop + start'
to `SIGHUP` for services that support `SIGHUP`.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-25 10:14:18 +01:00
Joachim Nilsson e303e1f833 Fix column alignment in initctl show for services not in current runlevel
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-25 09:36:56 +01:00
Joachim Nilsson 3ea4be9343 Fix NULL ptr dereference causing kernel panic
When `service_stop_done()` is called with a `NULL` argument and no
dynamic services have been stopped, this regression is triggered.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-25 09:30:53 +01:00
10 changed files with 169 additions and 56 deletions
+23
View File
@@ -3,6 +3,29 @@ Change Log
All relevant changes are documented in this file.
[2.3][] - 2015-11-28
--------------------
Bug fix release.
### Changes
* Add support for stop/start/restart/reload service by `name:id`
* Refactor service status listed in `initctl show`, show actual status
### Fixes
* Remove bootstrap-only tasks/services when leaving runlevel 'S'
* Fix reference counting issue with already stopped and removed services
when the user performs `initctl reload` to change system configuration
* Revert semantic change in behavior of `initctl restart`: users expect
service to be stopped/started, not reloaded with `SIGHUP` even if the
service supports it
* Fix `NULL` pointer dereference causing kernel panic when user calls
`initctl reload` after change of system configuration
* Fix column alignment in output of `initctl show` for services not in
current runlevel
[2.2][] - 2015-11-23
--------------------
+1 -1
View File
@@ -26,7 +26,7 @@
uninstall-exec uninstall-data uninstall-dev
#VERSION = $(shell git tag -l | tail -1)
VERSION = 2.2
VERSION = 2.3
NAME = finit
PKG = $(NAME)-$(VERSION)
DEV = $(NAME)-dev
+17 -16
View File
@@ -586,24 +586,25 @@ not return until the given command has fully completed.
Usage: initctl [OPTIONS] <COMMAND>
Options:
-d, --debug Debug initctl (client)
-v, --verbose Verbose output
-h, --help This help text
-d, --debug Debug initctl (client)
-v, --verbose Verbose output
-h, --help This help text
Commands:
debug Toggle Finit (daemon) debug
emit <EV> Emit an event. Can be a predefined event: RELOAD, STOP,
START, or a custom string to match the event list in a
service stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME,
where IFNAME is the interface name, e.g. eth0
reload Reload *.conf in /etc/finit.d/ and activate changes
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
status | show Show status of services
start <JOB|NAME> Start stopped job or service
stop <JOB|NAME> Stop/Pause running job or service
restart <JOB|NAME> Restart (stop/start) job or service
reload <JOB|NAME> Reload (SIGHUP) job or service
version Show Finit version
debug Toggle Finit (daemon) debug
help This help text
emit <EV> Emit event; a predefined event: RELOAD, STOP, START
or a custom string matching an event in a service
stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME. Where
IFNAME is the interface name, e.g. eth0
reload Reload *.conf in /etc/finit.d/ and activate changes
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
status | show Show status of services
start <JOB|NAME>[:ID] Start service by job# or name, with optional ID
stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name
restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name
reload <JOB|NAME>[:ID] Reload (SIGHUP) service by job# or name
version Show Finit version
```
The `emit <EV>` command can be used to send events to Finit. Built-in
+10 -5
View File
@@ -77,10 +77,10 @@ static int call(int (*action)(svc_t *), char *buf, size_t len)
token = strtok_r(input, " ", &pos);
while (token) {
svc_t *svc;
char *ptr = strchr(token, ':');
if (isdigit(token[0])) {
int job = atonum(token);
char *ptr = strchr(token, ':');
if (!ptr) {
svc = svc_job_iterator(1, job);
@@ -95,10 +95,15 @@ static int call(int (*action)(svc_t *), char *buf, size_t len)
}
} else {
svc = svc_named_iterator(1, token);
while (svc) {
result += action(svc);
svc = svc_named_iterator(0, token);
if (!ptr) {
svc = svc_named_iterator(1, token);
while (svc) {
result += action(svc);
svc = svc_named_iterator(0, token);
}
} else {
*ptr++ = 0;
result += action(svc_find_by_nameid(token, atonum(ptr)));
}
}
+1
View File
@@ -145,6 +145,7 @@ void conf_parse_events(svc_t *svc, char *events)
return;
}
svc->state = SVC_CONDHALT_STATE;
strlcpy(svc->events, ptr, sizeof(svc->events));
}
+2 -2
View File
@@ -43,9 +43,9 @@
int debug = 0;
int quiet = KERNEL_QUIET; /* Delayed disable of verbose mode. */
int verbose = VERBOSE_MODE;
int runlevel = 0; /* Bootstrap */
int runlevel = 0; /* Bootstrap 'S' */
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
int prevlevel = 0; /* HALT */
int prevlevel = -1;
char *sdown = NULL;
char *network = NULL;
char *username = NULL;
+25 -18
View File
@@ -149,14 +149,20 @@ static int show_status(char *UNUSED(arg))
}
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
char jobid[10], args[512] = "";
char jobid[10], args[512] = "", *lvls;
if (svc_is_unique(svc))
snprintf(jobid, sizeof(jobid), "%d", svc->job);
else
snprintf(jobid, sizeof(jobid), "%d:%d", svc->job, svc->id);
printf("%-5s %7s %-6d %-18.18s ", jobid, svc_status(svc), svc->pid, runlevel_string(svc->runlevels));
printf("%-5s %7s %-6d ", jobid, svc_status(svc), svc->pid);
lvls = runlevel_string(svc->runlevels);
if (strchr(lvls, '\e'))
printf("%-18.18s ", lvls);
else
printf("%-10.10s ", lvls);
if (!verbose) {
printf("%-20s %s\n", svc->cmd, svc->desc);
continue;
@@ -206,23 +212,24 @@ static int usage(int rc)
{
fprintf(stderr, "Usage: %s [OPTIONS] <COMMAND>\n\n"
"Options:\n"
" -d, --debug Debug initctl (client)\n"
" -v, --verbose Verbose output\n"
" -h, --help This help text\n\n"
" -d, --debug Debug initctl (client)\n"
" -v, --verbose Verbose output\n"
" -h, --help This help text\n\n"
"Commands:\n"
" debug Toggle Finit (daemon) debug\n"
" emit <EV> Emit an event. Can be a predefined event: RELOAD, STOP,\n"
" START, or a custom string to match the event list in a\n"
" service stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME,\n"
" where IFNAME is the interface name, e.g. eth0\n"
" reload Reload *.conf in /etc/finit.d/ and activate changes\n"
" runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot\n"
" status | show Show status of services\n"
" start <JOB|NAME> Start stopped job or service\n"
" stop <JOB|NAME> Stop/Pause running job or service\n"
" restart <JOB|NAME> Restart (stop/start) job or service\n"
" reload <JOB|NAME> Reload (SIGHUP) job or service\n"
" version Show Finit version\n\n", __progname);
" debug Toggle Finit (daemon) debug\n"
" help This help text\n"
" emit <EV> Emit event; a predefined event: RELOAD, STOP, START\n"
" or a custom string matching an event in a service\n"
" stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME. Where\n"
" IFNAME is the interface name, e.g. eth0\n"
" reload Reload *.conf in /etc/finit.d/ and activate changes\n"
" runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot\n"
" status | show Show status of services\n"
" start <JOB|NAME>[:ID] Start service by job# or name, with optional ID\n"
" stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name\n"
" restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name\n"
" reload <JOB|NAME>[:ID] Reload (SIGHUP) service by job# or name\n"
" version Show Finit version\n\n", __progname);
return rc;
}
+17 -8
View File
@@ -353,8 +353,6 @@ int service_stop(svc_t *svc, int state)
_d("Service %s state %d, new state %d, sighup %d", svc->cmd, svc->state, state, svc->sighup);
if (state == SVC_RELOAD_STATE && svc->sighup)
goto exit;
if (state == SVC_RESTART_STATE && svc->sighup)
return service_reload(svc);
if (runlevel != 1 && verbose)
print_desc("Stopping ", svc->desc);
@@ -406,7 +404,7 @@ static int service_stop_done(svc_t *svc)
plugin_run_hooks(HOOK_SVC_RECONF); /* Reconfigure HW/VLANs/etc here */
/* Finish off by starting/reload modified/new services */
if (svc->state == SVC_RELOAD_STATE)
if (svc && svc->state == SVC_RELOAD_STATE)
service_start_dynamic();
}
@@ -426,10 +424,15 @@ void service_stop_dynamic(void)
_d("Stopping disabled/removed services ...");
for (svc = svc_dynamic_iterator(1); svc; svc = svc_dynamic_iterator(0)) {
if (svc_is_changed(svc)) {
if (svc_is_changed(svc) && svc->pid) {
svc_state_t new_state = SVC_RELOAD_STATE;
if (svc_is_removed(svc))
new_state = SVC_HALTED_STATE;
dyn_stop_cnt++;
_d("Marking service %s as state %d", svc->cmd, SVC_RELOAD_STATE);
service_stop(svc, SVC_RELOAD_STATE);
_d("Marking service %s as state %d", svc->cmd, new_state);
service_stop(svc, new_state);
}
}
@@ -595,7 +598,8 @@ void service_runlevel(int newlevel)
else
erase("/etc/nologin");
if (0 != prevlevel)
/* No TTYs run at bootstrap, they have a delayed start. */
if (prevlevel > 0)
tty_runlevel(runlevel);
}
@@ -800,6 +804,7 @@ int service_register(int type, char *line, time_t mtime, char *username)
if (svc_is_inetd(svc)) {
char *iface, *name = service;
svc->state = SVC_WAITING_STATE;
if (svc->inetd.cmd && plugin)
name = plugin->name;
@@ -829,7 +834,8 @@ int service_register(int type, char *line, time_t mtime, char *username)
void service_unregister(svc_t *svc)
{
service_stop(svc, SVC_HALTED_STATE);
if (svc->state != SVC_HALTED_STATE)
_e("Failed stopping %s, removing anyway from list of monitored services.", svc->cmd);
svc_del(svc);
}
@@ -865,6 +871,9 @@ void service_monitor(pid_t lost)
if (lost != svc->pid)
continue;
if (!prevlevel && svc_clean_bootstrap(svc))
continue;
if (SVC_TYPE_SERVICE != svc->type) {
svc->pid = 0;
continue;
+71 -6
View File
@@ -310,6 +310,33 @@ svc_t *svc_find_by_jobid(int job, int id)
return NULL;
}
/**
* svc_find_by_nameid - Find an service object by its basename:ID
* @name: Process name to match
* @id: Instance id
*
* Returns:
* A pointer to an &svc_t object, or %NULL if not found.
*/
svc_t *svc_find_by_nameid(char *name, int id)
{
char *ptr;
svc_t *svc;
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
ptr = strrchr(svc->cmd, '/');
if (ptr)
ptr++;
else
ptr = svc->cmd;
if (svc->id == id && !strcmp(name, ptr))
return svc;
}
return NULL;
}
/**
* svc_mark_dynamic - Mark dynamically loaded services for deletion.
*
@@ -359,18 +386,56 @@ void svc_clean_dynamic(void (*cb)(svc_t *))
}
}
/**
* svc_clean_bootstrap - Remove bootstrap-only services after boot
* @svc: Pointer to &svc_t object
*
* Returns:
* %TRUE(1) if object was bootstrap-only, otherwise %FALSE(0)
*/
int svc_clean_bootstrap(svc_t *svc)
{
if (!ISOTHER(svc->runlevels, 0)) {
svc->pid = 0;
svc_del(svc);
return 1;
}
return 0;
}
char *svc_status(svc_t *svc)
{
if (svc->pid)
return "running";
if (!svc_in_runlevel(svc, runlevel))
return "halted";
return "stopped";
if (svc_is_inetd(svc))
switch (svc->state) {
case SVC_WAITING_STATE:
return "waiting";
return "stopped";
case SVC_PAUSED_STATE:
return "paused";
case SVC_CONDHALT_STATE:
return "nocond";
case SVC_RESTART_STATE:
return "restart";
case SVC_RELOAD_STATE:
return "reload";
case SVC_RUNNING_STATE:
if (svc->pid)
return "running";
/* Fall through */
case SVC_HALTED_STATE:
default:
break;
}
return "halted";
}
/* Same base service, return unique ID */
+2
View File
@@ -131,6 +131,7 @@ int svc_del (svc_t *svc);
svc_t *svc_find (char *cmd, int id);
svc_t *svc_find_by_pid (pid_t pid);
svc_t *svc_find_by_jobid (int job, int id);
svc_t *svc_find_by_nameid (char *name, int id);
svc_t *svc_iterator (int first);
svc_t *svc_inetd_iterator (int first);
@@ -144,6 +145,7 @@ void svc_foreach_dynamic (void (*cb)(svc_t *));
void svc_mark_dynamic (void);
void svc_check_dirty (svc_t *svc, time_t mtime);
void svc_clean_dynamic (void (*cb)(svc_t *));
int svc_clean_bootstrap (svc_t *svc);
char *svc_status (svc_t *svc);
int svc_next_id (char *cmd);