mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4d3ec1a9f | ||
|
|
51befb492c | ||
|
|
7850378e15 | ||
|
|
438d6b4e63 | ||
|
|
712f68f9da |
+22
-2
@@ -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
@@ -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])
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user