Compare commits

...
5 Commits
Author SHA1 Message Date
Joachim Wiberg f4d3ec1a9f Update ChangeLog and bump version for v4.4 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-05-15 16:40:56 +02:00
Joachim Wiberg 51befb492c Allow conflicting services to start when conflict is resolved
These changes add a new svc_block_t type: SVC_BLOCK_CONFLICT so a user
can more clearly see why a run/task/service has not been started by
Finit.  The reason for the block is by default logged, which can be
escaped by using the `nowarn` flag.

Also, when the conflict is resolved, allow the service to start.

With these changes, the system/hotplug.conf should work better and
cause less questions about "strange" log messages.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-05-15 16:23:40 +02:00
Joachim Wiberg 7850378e15 Fix issue with messed up linewrap in qemu-system-x86_64
Apparently the qemu-system-x86_64 in -nographics mode does all sorts of
crazy things to the terminal.  Most annoying, it disables linewrap.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-05-15 16:05:59 +02:00
Joachim Wiberg 438d6b4e63 Document fix of regression from Finit v3.2
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-05-14 09:33:10 +02:00
Joachim Wiberg 712f68f9da Fix #355: regression stopping a process and its group
In 91a9c83 a regression was introduced that affects the way Finit stops
a supervised process and its process group.

Instead of sending SIGTERM to the process, delegating the responsibility
to that process to inform any children it may have, Finit as of 91a9c83
sends SIGTERM to the entire process group.  For SIGKILL this is fine,
SIGKILL only runs as cleanup and as a last ditch effort if the process
doesn't respond to SIGTERM.

This regression, introduced in v3.2, directly affects services like
avahi-autoipd that have forked off children that it needs to tell to
exit cleanly before it returns. With the patch in question these
children are never allowed to complete, which in turn causes lingering
169.254 link-local addresses on interfaces.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-05-14 09:27:09 +02:00
7 changed files with 69 additions and 17 deletions
+22 -2
View File
@@ -4,8 +4,8 @@ Change Log
All relevant changes are documented in this file.
[4.4][UNRELEASED]
-----------------
[4.4][] - 2023-05-15
--------------------
> **Note 1:** this release contains changes to the `.conf` parser. If you
> have .conf file statements with comment character (`#`) in the command
@@ -307,6 +307,23 @@ All relevant changes are documented in this file.
reload, halt, poweroff, suspend. Also, prevent `SIGHUP` and `SIGUSR1`
signals when in shutdown or reboot
* Fix #352: separate runlevel S from runlevel 0
* Fix #355: regression in v3.2 stopping a process and its group
In Finit v3.2 a regression was introduced that affects the way Finit
stops a supervised process and its process group.
Instead of sending SIGTERM to the process, and thus delegating the
responsibility to that process to inform any children it may have, as
of commit 91a9c83 Finit sends SIGTERM to the entire process group.
For SIGKILL this is fine, SIGKILL only runs as cleanup and as a last
ditch effort if the process doesn't respond to SIGTERM.
This regression, introduced in v3.2, directly affects services like
`avahi-autoipd` that have forked off children that it needs to tell to
exit cleanly before it returns. With the patch in question these
children are never allowed to complete, which in turn causes lingering
169.254 link-local addresses on interfaces.
* Fix bootmisc plugin: octal permission on `/run/lock` and `/var/lock`
* Ensure `initctl cond get` support the flux state (exit code 255)
@@ -340,6 +357,9 @@ All relevant changes are documented in this file.
However, on `initctl reload` (and no change to .conf files) the arg
list was lost while parsing the .conf files. Leading to a false
positive 'diff' in args causing nginx to be unnecessarily restarted.
* Fix issue with disabled "linewrap" on the console TTY after login.
The root cause is `qemu-system-x86_64 -nographics` disabling it when
starting up. The correct `\e[?7h` escape code is now used.
[4.3][] - 2022-05-15
+1 -1
View File
@@ -1,4 +1,4 @@
AC_INIT([Finit],[4.4-rc2],[https://github.com/troglobit/finit/issues],[finit],[https://troglobit.com/projects/finit/])
AC_INIT([Finit],[4.4],[https://github.com/troglobit/finit/issues],[finit],[https://troglobit.com/projects/finit/])
AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
AM_SILENT_RULES([yes])
+2
View File
@@ -65,6 +65,7 @@ static int stop(svc_t *svc, void *user_data)
service_timeout_cancel(svc);
svc_stop(svc);
service_step(svc);
service_step_all(SVC_TYPE_ANY);
return 0;
}
@@ -77,6 +78,7 @@ static int start(svc_t *svc, void *user_data)
service_timeout_cancel(svc);
svc_start(svc);
service_step(svc);
service_step_all(SVC_TYPE_ANY);
return 0;
}
+3
View File
@@ -84,6 +84,9 @@ char *console(void)
void console_init(void)
{
/* Enable line wrap, if disabled previously, e.g., qemu */
dprint(STDOUT_FILENO, "\033[?7h", 5);
log_init();
}
+33 -13
View File
@@ -173,7 +173,7 @@ static int service_script_del(pid_t pid)
if (ptr->pid != pid)
continue;
dbg("Collected service %s script PID %d.", svc_ident(ptr->svc, NULL, 0), pid);
dbg("Collected service %s script PID %d, killing process group.", svc_ident(ptr->svc, NULL, 0), pid);
service_timeout_cancel(ptr->svc);
kill(-ptr->pid, SIGKILL);
TAILQ_REMOVE(&svc_assoc_list, ptr, link);
@@ -610,13 +610,6 @@ static int service_start(svc_t *svc)
}
}
/* Don't start if it conflicts with something else already started */
if (svc_conflicts(svc)) {
logit(LOG_INFO, "Not starting %s, conflicts with %s",
svc_ident(svc, NULL, 0), svc->conflict);
return 1;
}
compose_cmdline(svc, cmdline, sizeof(cmdline));
if (svc_is_sysv(svc))
logit(LOG_CONSOLE | LOG_NOTICE, "Calling '%s start' ...", cmdline);
@@ -865,7 +858,7 @@ static void service_kill(svc_t *svc)
return;
}
dbg("%s: Sending SIGKILL to pid:%d", pid_get_name(svc->pid, NULL, 0), svc->pid);
dbg("%s: Sending SIGKILL to process group %d", pid_get_name(svc->pid, NULL, 0), svc->pid);
logit(LOG_CONSOLE | LOG_NOTICE, "Stopping %s[%d], sending SIGKILL ...",
svc_ident(svc, NULL, 0), svc->pid);
if (runlevel != 1)
@@ -969,9 +962,14 @@ int service_stop(svc_t *svc)
if (!svc_is_sysv(svc)) {
if (svc->pid > 1) {
/* Kill all children in the same proess group, e.g. logit */
rc = kill(-svc->pid, svc->sighalt);
dbg("kill(-%d, %d) => rc %d, errno %d", svc->pid, svc->sighalt, rc, errno);
/*
* Send SIGTERM to parent process of process group, not to the
* entire group. This gives the process time to properly stop
* and/or forward TERM to its children. If it does not respond
* in within a reasonable timeout we SIGKILL the entire group.
*/
rc = kill(svc->pid, svc->sighalt);
dbg("kill(%d, %d) => rc %d, errno %d", svc->pid, svc->sighalt, rc, errno);
/* PID lost or forking process never really started */
if (rc == -1 && (errno == ESRCH || errno == ENOENT)) {
service_cleanup(svc);
@@ -1732,6 +1730,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
else
memset(svc->ifstmt, 0, sizeof(svc->ifstmt));
svc->manual = manual;
svc->nowarn = nowarn;
svc->respawn = respawn;
svc->forking = forking;
svc->restart_max = restart_max;
@@ -1837,6 +1836,8 @@ void service_monitor(pid_t lost, int status)
dbg("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d",
svc->state == SVC_CLEANUP_STATE ? svc->post_script : svc->pre_script,
lost, WIFEXITED(status), WIFSIGNALED(status), WEXITSTATUS(status));
/* Kill all children in the same proess group, e.g. logit */
dbg("Killing lingering children in same process group ...");
kill(-svc->pid, SIGKILL);
goto done;
@@ -1858,8 +1859,8 @@ void service_monitor(pid_t lost, int status)
logit(LOG_CONSOLE | LOG_NOTICE, "Stopped %s[%d]", svc_ident(svc, NULL, 0), lost);
}
/* Terminate any children in the same proess group, e.g. logit */
dbg("Killing lingering children in same process group ...");
kill(-svc->pid, SIGKILL);
/* Try removing PID file (in case service does not clean up after itself) */
@@ -2269,6 +2270,15 @@ restart:
case SVC_HALTED_STATE:
if (enabled)
svc_set_state(svc, SVC_WAITING_STATE);
else {
if (svc_is_conflict(svc)) {
logit(svc->nowarn ? LOG_DEBUG : LOG_INFO,
"%s in conflict with %s, checking again ...",
svc_ident(svc, NULL, 0), svc->conflict);
if (!svc_conflicts(svc))
svc_unblock(svc);
}
}
break;
case SVC_DONE_STATE:
@@ -2335,6 +2345,16 @@ restart:
if (sm_is_in_teardown(&sm))
break;
/* Don't start if it conflicts with something else already started */
if (svc_conflicts(svc)) {
logit(svc->nowarn ? LOG_DEBUG : LOG_INFO,
"Not starting %s, conflicts with %s",
svc_ident(svc, NULL, 0), svc->conflict);
svc_conflict(svc);
svc_set_state(svc, SVC_HALTED_STATE);
break;
}
if (svc_has_pre(svc)) {
svc_set_state(svc, SVC_SETUP_STATE);
service_pre_script(svc);
+1 -1
View File
@@ -132,7 +132,7 @@ void stty(int fd, speed_t speed)
dprint(fd, "\033[?25h", 6);
/* Enable line wrap, if disabled previously */
dprint(fd, "\033[7h", 4);
dprint(fd, "\033[?7h", 5);
}
/**
+7
View File
@@ -74,6 +74,7 @@ typedef enum {
SVC_BLOCK_USER,
SVC_BLOCK_BUSY,
SVC_BLOCK_RESTARTING,
SVC_BLOCK_CONFLICT,
} svc_block_t;
typedef enum {
@@ -125,6 +126,7 @@ typedef struct svc {
svc_type_t type; /* Service, run, task, ... */
char protect; /* Services like dbus-daemon & udev by Finit */
char manual; /* run/task that require `initctl start foo` */
char nowarn; /* Skip or log warning if cmd missing or conflicts */
const int dirty; /* 0: unmodified, 1: modified */
const int removed;
int starting; /* ... waiting for pidfile to be re-asserted */
@@ -270,6 +272,7 @@ static inline int svc_is_busy (svc_t *svc) { return svc && svc->block == SV
static inline int svc_is_missing (svc_t *svc) { return svc && svc->block == SVC_BLOCK_MISSING; }
static inline int svc_is_crashing (svc_t *svc) { return svc && svc->block == SVC_BLOCK_CRASHING; }
static inline int svc_is_restart (svc_t *svc) { return svc && svc->block == SVC_BLOCK_RESTARTING; }
static inline int svc_is_conflict (svc_t *svc) { return svc && svc->block == SVC_BLOCK_CONFLICT; }
static inline void svc_unblock (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_NONE; }
#define svc_start(svc) svc_unblock(svc)
@@ -278,6 +281,7 @@ static inline void svc_busy (svc_t *svc) { if (svc) svc->block = SVC_BLOC
static inline void svc_missing (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_MISSING; }
static inline void svc_restarting (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_RESTARTING; }
static inline void svc_crashing (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_CRASHING; }
static inline void svc_conflict (svc_t *svc) { if (svc) svc->block = SVC_BLOCK_CONFLICT; }
/* Has condition in configuration and cond is allowed? */
static inline int svc_has_cond(svc_t *svc)
@@ -350,6 +354,9 @@ static inline char *svc_status(svc_t *svc)
case SVC_BLOCK_RESTARTING:
return "restart";
case SVC_BLOCK_CONFLICT:
return "conflict";
}
return "unknown";