mirror of
https://github.com/troglobit/finit.git
synced 2026-10-13 10:14:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9245869e18 | ||
|
|
0f4a487328 | ||
|
|
f1b5b42919 | ||
|
|
f546129baf | ||
|
|
27451ac3f2 | ||
|
|
0a8f3a6250 | ||
|
|
70c4e7d774 | ||
|
|
5265eee25d | ||
|
|
4b06e1a49f | ||
|
|
6b9aa21509 | ||
|
|
990307fbc9 | ||
|
|
9d8a9b7fba | ||
|
|
bbc83eaa64 | ||
|
|
23d034f521 | ||
|
|
9a3148a49d | ||
|
|
8560103a24 | ||
|
|
7a75e34808 | ||
|
|
4d4fc10d57 | ||
|
|
003faae9e9 | ||
|
|
01a01d65c0 | ||
|
|
048302f06a | ||
|
|
74f0fcfccd | ||
|
|
3cfe0a33b8 | ||
|
|
465bc17ca4 | ||
|
|
d4889b435d | ||
|
|
49c0557ced | ||
|
|
6be16f2f6d | ||
|
|
bc8118d515 | ||
|
|
0c0e880f3f | ||
|
|
119e66a7e9 | ||
|
|
46ffa81f5c |
@@ -21,7 +21,6 @@ jobs:
|
|||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
env:
|
env:
|
||||||
MAKEFLAGS: -j3
|
|
||||||
CC: ${{ matrix.compiler }}
|
CC: ${{ matrix.compiler }}
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -33,14 +32,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix= --enable-static
|
./configure --prefix= --enable-static
|
||||||
make V=1
|
make -j3 V=1
|
||||||
- name: Regular Finit
|
- name: Regular Finit
|
||||||
run: |
|
run: |
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||||
--with-keventd
|
--with-keventd
|
||||||
make clean
|
make -j3 clean
|
||||||
make V=1
|
make -j3 V=1
|
||||||
- name: Install to /tmp
|
- name: Install to /tmp
|
||||||
run: |
|
run: |
|
||||||
DESTDIR=/tmp make install-strip
|
DESTDIR=/tmp make install-strip
|
||||||
@@ -57,6 +56,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo /tmp/sbin/finit -h
|
sudo /tmp/sbin/finit -h
|
||||||
sudo /tmp/sbin/initctl -h
|
sudo /tmp/sbin/initctl -h
|
||||||
|
- name: Enable unprivileged userns (unshare)
|
||||||
|
run: |
|
||||||
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
- name: Run Unit Tests
|
- name: Run Unit Tests
|
||||||
run: |
|
run: |
|
||||||
make check || (cat test/test-suite.log; false)
|
make check || (cat test/test-suite.log; false)
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ jobs:
|
|||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||||
--with-keventd
|
--with-keventd
|
||||||
|
- name: Enable unprivileged userns (unshare)
|
||||||
|
run: |
|
||||||
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
- name: Build release ...
|
- name: Build release ...
|
||||||
run: |
|
run: |
|
||||||
make release || (cat test/test-suite.log; false)
|
make release || (cat test/test-suite.log; false)
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ jobs:
|
|||||||
- name: Install to /tmp
|
- name: Install to /tmp
|
||||||
run: |
|
run: |
|
||||||
DESTDIR=/tmp make install-strip
|
DESTDIR=/tmp make install-strip
|
||||||
|
- name: Enable unprivileged userns (unshare)
|
||||||
|
run: |
|
||||||
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
- name: Check dist tarball
|
- name: Check dist tarball
|
||||||
run: |
|
run: |
|
||||||
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
||||||
|
|||||||
+38
-1
@@ -4,6 +4,42 @@ Change Log
|
|||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
|
||||||
|
[4.9][] - 2025-02-15
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> This release changes how Finit reacts to the exit status of `pre:`
|
||||||
|
> scripts. Finit will now no longer start the main process if its
|
||||||
|
> `pre:` script fails for any reason. So, if you have pre scripts that,
|
||||||
|
> e.g., create directories, make sure they are idempotent.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Add individual timeout (optional) support for pre/post/ready scripts
|
||||||
|
- Add support for systems with broken RTC, i.e., those that at power-on
|
||||||
|
may reset the RTC to a random date instead of zero, issue #418
|
||||||
|
- Add support for detecting "in-container" when in `systemd-nspawn`
|
||||||
|
- Check exit status of `pre:` scripts, on failure drive service/sysv to
|
||||||
|
`crashed` state. (The exit code of `post:` scripts remain ignored)
|
||||||
|
- All pre/post/ready scripts are now also searched for in `$PATH`
|
||||||
|
- Reset color attributes and clear screen when starting up. This is
|
||||||
|
for boot loaders like GRUB, which leave background color artifacts
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #415: only mark reverse-dependencies "dirty" if the main service
|
||||||
|
does not support SIGHUP. This helps avoid unnecessary restarts of
|
||||||
|
services that depend on a service that supports SIGHUP
|
||||||
|
- Fix #417: leaking inotify watchers in the cgroup subsystem
|
||||||
|
- Fix #421: add support for `nofail` mount option in `/etc/fstab`
|
||||||
|
- Fix #425: ordering bug in detecting .conf file changes to services
|
||||||
|
and `initctl reload`, or runlevel changes
|
||||||
|
- Fix `initctl touch` of template services, previously marking a
|
||||||
|
service created from a template as "dirty" did not take
|
||||||
|
- Fix unintended restart of template "siblings". I.e., `initctl touch`
|
||||||
|
of instantiated template service A affected B from same template
|
||||||
|
- Fix buggy `--with-rtc-date=DATE` configure option
|
||||||
|
- Fix kill on timeout of pre/post/ready scripts
|
||||||
|
|
||||||
|
|
||||||
[4.8][] - 2024-10-13
|
[4.8][] - 2024-10-13
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -1704,7 +1740,8 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.8...HEAD
|
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.9...HEAD
|
||||||
|
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
|
||||||
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
||||||
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
||||||
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
||||||
|
|||||||
+15
-3
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([Finit], [4.8], [https://github.com/troglobit/finit/issues],
|
AC_INIT([Finit], [4.9], [https://github.com/troglobit/finit/issues],
|
||||||
[finit], [https://troglobit.com/projects/finit/])
|
[finit], [https://troglobit.com/projects/finit/])
|
||||||
AC_CONFIG_AUX_DIR(aux)
|
AC_CONFIG_AUX_DIR(aux)
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
||||||
@@ -177,9 +177,13 @@ AC_ARG_WITH(plugin-path,
|
|||||||
[plugin_path=$withval], [plugin_path=yes])
|
[plugin_path=$withval], [plugin_path=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(rtc-date,
|
AC_ARG_WITH(rtc-date,
|
||||||
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM", default "2000-01-01 00:00"]),
|
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM:SS", default "2000-01-01 00:00:00"]),
|
||||||
[rtc_date=$withval], [rtc_date=no])
|
[rtc_date=$withval], [rtc_date=no])
|
||||||
|
|
||||||
|
AC_ARG_WITH(rtc-file,
|
||||||
|
AS_HELP_STRING([--with-rtc-file=FILE], [If RTC is missing, save and restore system clock from this file, default: no]),
|
||||||
|
[rtc_file=$withval], [rtc_file=no])
|
||||||
|
|
||||||
### Enable features ###########################################################################
|
### Enable features ###########################################################################
|
||||||
|
|
||||||
# Create config.h from selected features and fallback defaults
|
# Create config.h from selected features and fallback defaults
|
||||||
@@ -278,9 +282,16 @@ AS_IF([test "x$with_random_seed" != "xno"], [
|
|||||||
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
||||||
|
|
||||||
AS_IF([test "x$rtc_date" != "xno"], [
|
AS_IF([test "x$rtc_date" != "xno"], [
|
||||||
AC_DEFINE(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
AC_DEFINE_UNQUOTED(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
||||||
rtc_date=""])
|
rtc_date=""])
|
||||||
|
|
||||||
|
AS_IF([test "x$rtc_file" != "xno"], [
|
||||||
|
AS_IF([test "x$rtc_file" = "xyes"], [
|
||||||
|
rtc_file=/var/lib/misc/rtc])
|
||||||
|
AC_EXPAND_DIR(rtcfile_path, "$rtc_file")
|
||||||
|
AC_DEFINE_UNQUOTED(RTC_FILE, "$rtcfile_path", [Save and restore system time from this file if /dev/rtc is missing.])],[
|
||||||
|
AC_DEFINE_UNQUOTED(RTC_FILE, NULL)])
|
||||||
|
|
||||||
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
||||||
|
|
||||||
AS_IF([test "x$with_sulogin" != "xno"], [
|
AS_IF([test "x$with_sulogin" != "xno"], [
|
||||||
@@ -387,6 +398,7 @@ Behavior:
|
|||||||
Boot heading..........: $heading
|
Boot heading..........: $heading
|
||||||
Plugins...............: $plugins
|
Plugins...............: $plugins
|
||||||
RTC restore date......: $RTC_DATE
|
RTC restore date......: $RTC_DATE
|
||||||
|
RTC fallback file.....: $rtc_file
|
||||||
|
|
||||||
Optional features:
|
Optional features:
|
||||||
Install doc/..........: $enable_doc
|
Install doc/..........: $enable_doc
|
||||||
|
|||||||
+32
-20
@@ -890,33 +890,45 @@ configurable with the following options:
|
|||||||
* `oncrash:script` -- similarly, but instead of rebooting, call the
|
* `oncrash:script` -- similarly, but instead of rebooting, call the
|
||||||
`post:script` action if set, see below.
|
`post:script` action if set, see below.
|
||||||
|
|
||||||
When stopping a service (run/task/sysv/service), either manually or
|
When stopping a service (run/task/sysv/service), either manually or when
|
||||||
when moving to another runlevel, Finit starts by sending `SIGTERM`, to
|
moving to another runlevel, Finit starts by sending `SIGTERM`, to allow
|
||||||
allow the process to shut down gracefully. If the process has not
|
the process to shut down gracefully. However, if the process has not
|
||||||
been collected within 3 seconds, Finit sends `SIGKILL`. To halt the
|
been collected within 3 seconds, Finit will send `SIGKILL`. To stop the
|
||||||
process using a different signal, use the option `halt:SIGNAL`, e.g.,
|
process using a different signal than `SIGTERM`, use `halt:SIGNAL`,
|
||||||
`halt:SIGPWR`. To change the delay between your halt signal and KILL,
|
e.g., `halt:SIGPWR`. To change the delay between the stop signal and
|
||||||
use the option `kill:SEC`, e.g., `kill:10` to wait 10 seconds before
|
KILL, use the option `kill:<1-60>`, e.g., `kill:10` to wait 10 seconds
|
||||||
sending `SIGKILL`.
|
before sending `SIGKILL`.
|
||||||
|
|
||||||
Services support `pre:script` and `post:script` actions as well. These
|
Services, including the `sysv` variant, support pre/post/ready scripts:
|
||||||
run as the same `@USER:GROUP` as the service itself, with any `env:file`
|
|
||||||
sourced. The scripts must use an absolute path, but are executed from
|
* `pre:[0-3600,]script`
|
||||||
the `$HOME` of the given user. The scripts are not called with any
|
* `post:[0-3600,]script`
|
||||||
argument (currently), but both get the `SERVICE_IDENT=foo` environment
|
* `ready:[0-3600,]script`
|
||||||
variable set. Here `foo` denotes the identity of the service, which if
|
|
||||||
there are multiple services named `foo`, may be `foo:1`, or any unique
|
The optional number (0-3600) is the timeout before Finit kills the
|
||||||
identifier specified in the .conf file. The `post:script` is called
|
script, it defaults to the kill delay value and can be disabled by
|
||||||
with an additional set of environment variables:
|
setting it to zero. These scripts run as the same `@USER:GROUP` as the
|
||||||
|
service itself, with any `env:file` sourced. The scripts must use an
|
||||||
|
absolute path, but are executed from the `$HOME` of the given user. The
|
||||||
|
scripts are not called with any argument, but get a set of environment
|
||||||
|
variables:
|
||||||
|
|
||||||
|
* `SERVICE_IDENT=foo:1`
|
||||||
|
* `SERVICE_NAME=foo`
|
||||||
|
* `SERVICE_ID=1`
|
||||||
|
|
||||||
|
The `post:script` is called with an additional set of environment
|
||||||
|
variables:
|
||||||
|
|
||||||
- `EXIT_CODE=[exited,signal]`: set to one of `exited` or `signal`
|
- `EXIT_CODE=[exited,signal]`: set to one of `exited` or `signal`
|
||||||
- `EXIT_STATUS=[num,SIGNAME]`: set to one of exit status code from
|
- `EXIT_STATUS=[num,SIGNAME]`: set to one of exit status code from
|
||||||
the program, if it exited normally, or the signal name (`HUP`,
|
the program, if it exited normally, or the signal name (`HUP`,
|
||||||
`TERM`, etc.) if it exited due to signal
|
`TERM`, etc.) if it exited due to signal
|
||||||
|
|
||||||
These script actions *must terminate*, so they have a default execution
|
> [!IMPORTANT]
|
||||||
time of 3 seconds before they are SIGKILLed, this can be adjusted using
|
> These script actions are intended for setup, cleanup, and readiness
|
||||||
the above `kill:SEC` syntax.
|
> notification. It is up to the user to ensure the scripts terminate.
|
||||||
|
|
||||||
|
|
||||||
#### Conditional Loading
|
#### Conditional Loading
|
||||||
|
|
||||||
|
|||||||
+180
-64
@@ -36,8 +36,15 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
/* Kernel RTC driver validates against this date for sanity check */
|
/*
|
||||||
|
* Kernel RTC driver validates against this date for sanity check. The
|
||||||
|
* on NTP sync the driver can also update the RTC every 11 mins. We use
|
||||||
|
* the same update interval to handle manual time set and file save.
|
||||||
|
*/
|
||||||
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
|
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
|
||||||
|
#define RTC_FMT "%Y-%m-%d %H:%M:%S"
|
||||||
|
#define RTC_PERIOD (11 * 60 * 1000)
|
||||||
|
|
||||||
#ifdef RTC_TIMESTAMP_CUSTOM
|
#ifdef RTC_TIMESTAMP_CUSTOM
|
||||||
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
|
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
|
||||||
#else
|
#else
|
||||||
@@ -45,6 +52,10 @@ static char *rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
|||||||
#endif
|
#endif
|
||||||
static time_t rtc_date_fallback = 946684800LL;
|
static time_t rtc_date_fallback = 946684800LL;
|
||||||
|
|
||||||
|
static char *rtc_file = RTC_FILE;
|
||||||
|
static uev_t rtc_timer;
|
||||||
|
|
||||||
|
|
||||||
static void tz_set(char *tz, size_t len)
|
static void tz_set(char *tz, size_t len)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@@ -68,6 +79,125 @@ static void tz_restore(char *tz)
|
|||||||
tzset();
|
tzset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int time_set(struct tm *tm)
|
||||||
|
{
|
||||||
|
struct tm fallback = { 0 };
|
||||||
|
struct timeval tv = { 0 };
|
||||||
|
char tz[128];
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
tz_set(tz, sizeof(tz));
|
||||||
|
|
||||||
|
if (!tm) {
|
||||||
|
logit(LOG_NOTICE, "Resetting system clock to kernel default, %s.", rtc_timestamp);
|
||||||
|
tm = &fallback;
|
||||||
|
|
||||||
|
/* Attempt to set RTC to a sane value ... */
|
||||||
|
tv.tv_sec = rtc_date_fallback;
|
||||||
|
if (!gmtime_r(&tv.tv_sec, tm)) {
|
||||||
|
rc = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tm->tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
||||||
|
tv.tv_sec = mktime(tm);
|
||||||
|
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
||||||
|
errno = EINVAL;
|
||||||
|
rc = 2;
|
||||||
|
} else {
|
||||||
|
if (settimeofday(&tv, NULL) == -1)
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
tz_restore(tz);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int time_get(struct tm *tm)
|
||||||
|
{
|
||||||
|
struct timeval tv = { 0 };
|
||||||
|
char tz[128];
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
tz_set(tz, sizeof(tz));
|
||||||
|
|
||||||
|
rc = gettimeofday(&tv, NULL);
|
||||||
|
if (rc < 0 || tv.tv_sec < rtc_date_fallback)
|
||||||
|
rc = 2;
|
||||||
|
else
|
||||||
|
gmtime_r(&tv.tv_sec, tm);
|
||||||
|
|
||||||
|
tz_restore(tz);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void file_save(void *arg)
|
||||||
|
{
|
||||||
|
struct tm tm = { 0 };
|
||||||
|
int rc = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (!rtc_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fp = fopen(rtc_file, "w");
|
||||||
|
if (!fp) {
|
||||||
|
logit(LOG_WARNING, "Failed saving system clock to %s, code %d: %s",
|
||||||
|
rtc_file, errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = time_get(&tm))) {
|
||||||
|
logit(LOG_WARNING, "System clock invalid, before %s, not saving", rtc_timestamp);
|
||||||
|
print_desc(NULL, "System clock invalid, skipping");
|
||||||
|
} else {
|
||||||
|
char buf[32] = { 0 };
|
||||||
|
|
||||||
|
print_desc(NULL, "Saving system clock to file");
|
||||||
|
strftime(buf, sizeof(buf), RTC_FMT, &tm);
|
||||||
|
fprintf(fp, "%s\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(rc, NULL);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void file_restore(void *arg)
|
||||||
|
{
|
||||||
|
struct tm tm = { 0 };
|
||||||
|
int rc = 1;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (!rtc_file) {
|
||||||
|
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_desc(NULL, "Restoring system clock from backup");
|
||||||
|
|
||||||
|
fp = fopen(rtc_file, "r");
|
||||||
|
if (fp) {
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
if (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
chomp(buf);
|
||||||
|
strptime(buf, RTC_FMT, &tm);
|
||||||
|
rc = time_set(&tm);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
} else
|
||||||
|
logit(LOG_WARNING, "Missing %s", rtc_file);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
time_set(NULL);
|
||||||
|
rc = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
print(rc, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int rtc_open(void)
|
static int rtc_open(void)
|
||||||
{
|
{
|
||||||
char *alt[] = {
|
char *alt[] = {
|
||||||
@@ -91,10 +221,8 @@ static int rtc_open(void)
|
|||||||
|
|
||||||
static void rtc_save(void *arg)
|
static void rtc_save(void *arg)
|
||||||
{
|
{
|
||||||
struct timeval tv = { 0 };
|
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
int fd, rc = 0;
|
int fd, rc = 0;
|
||||||
char tz[128];
|
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
@@ -105,38 +233,26 @@ static void rtc_save(void *arg)
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tz_set(tz, sizeof(tz));
|
if ((rc = time_get(&tm))) {
|
||||||
rc = gettimeofday(&tv, NULL);
|
|
||||||
if (rc < 0 || tv.tv_sec < rtc_date_fallback) {
|
|
||||||
print_desc(NULL, "System clock invalid, not saving to RTC");
|
print_desc(NULL, "System clock invalid, not saving to RTC");
|
||||||
invalid:
|
} else {
|
||||||
logit(LOG_ERR, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
|
print_desc(NULL, "Saving system clock (UTC) to RTC");
|
||||||
|
rc = ioctl(fd, RTC_SET_TIME, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc && errno == EINVAL) {
|
||||||
|
logit(LOG_WARNING, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
|
||||||
rc = 2;
|
rc = 2;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_desc(NULL, "Saving system time (UTC) to RTC");
|
|
||||||
|
|
||||||
gmtime_r(&tv.tv_sec, &tm);
|
|
||||||
if (ioctl(fd, RTC_SET_TIME, &tm) < 0) {
|
|
||||||
if (EINVAL == errno)
|
|
||||||
goto invalid;
|
|
||||||
rc = 1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
tz_restore(tz);
|
|
||||||
print(rc, NULL);
|
print(rc, NULL);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtc_restore(void *arg)
|
static void rtc_restore(void *arg)
|
||||||
{
|
{
|
||||||
struct timeval tv = { 0 };
|
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
int fd, rc = 0;
|
int fd, rc = 0;
|
||||||
char tz[128];
|
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
@@ -145,66 +261,62 @@ static void rtc_restore(void *arg)
|
|||||||
|
|
||||||
fd = rtc_open();
|
fd = rtc_open();
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
|
file_restore(arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tz_set(tz, sizeof(tz));
|
if ((rc = ioctl(fd, RTC_RD_TIME, &tm)) < 0) {
|
||||||
if (ioctl(fd, RTC_RD_TIME, &tm) < 0) {
|
|
||||||
char msg[120];
|
char msg[120];
|
||||||
|
|
||||||
snprintf(msg, sizeof(msg), "Failed restoring system clock, %s",
|
snprintf(msg, sizeof(msg), "Failed restoring system clock, %s",
|
||||||
EINVAL == errno ? "RTC time is too old" :
|
EINVAL == errno ? "RTC time is too old" :
|
||||||
ENOENT == errno ? "RTC has no saved time" : "see log for details");
|
ENOENT == errno ? "RTC has no saved time" : "see log for details");
|
||||||
print_desc(NULL, msg);
|
print_desc(NULL, msg);
|
||||||
|
} else {
|
||||||
invalid:
|
|
||||||
logit(LOG_ERR, "Failed restoring system clock from RTC.");
|
|
||||||
if (EINVAL == errno)
|
|
||||||
logit(LOG_ERR, "RTC time is too old (before %s)", rtc_timestamp);
|
|
||||||
else if (ENOENT == errno)
|
|
||||||
logit(LOG_ERR, "RTC has no previously saved (valid) time.");
|
|
||||||
else
|
|
||||||
logit(LOG_ERR, "RTC error code %d: %s", errno, strerror(errno));
|
|
||||||
|
|
||||||
/* Been here already? */
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Attempt to set RTC to a sane value ... */
|
|
||||||
tv.tv_sec = rtc_date_fallback;
|
|
||||||
if (!gmtime_r(&tv.tv_sec, &tm))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
logit(LOG_NOTICE, "Resetting RTC to kernel default, %s.", rtc_timestamp);
|
|
||||||
rc = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rc)
|
|
||||||
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||||
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
rc = time_set(&tm);
|
||||||
tv.tv_sec = mktime(&tm);
|
|
||||||
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
|
||||||
errno = EINVAL;
|
|
||||||
goto invalid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settimeofday(&tv, NULL) == -1)
|
if (rc) {
|
||||||
rc = 1;
|
logit(LOG_WARNING, "Failed restoring system clock from RTC.");
|
||||||
|
if (EINVAL == errno)
|
||||||
|
logit(LOG_WARNING, "RTC time is too old (before %s)", rtc_timestamp);
|
||||||
|
else if (ENOENT == errno)
|
||||||
|
logit(LOG_WARNING, "RTC has no previously saved (valid) time.");
|
||||||
|
else
|
||||||
|
logit(LOG_WARNING, "RTC error code %d: %s", errno, strerror(errno));
|
||||||
|
|
||||||
|
print(2, NULL);
|
||||||
|
|
||||||
|
/* Try restoring from last save game */
|
||||||
|
if (rtc_file)
|
||||||
|
file_restore(arg);
|
||||||
|
} else
|
||||||
|
print(0, NULL);
|
||||||
|
|
||||||
out:
|
|
||||||
tz_restore(tz);
|
|
||||||
print(rc, NULL);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void save(void *arg)
|
||||||
|
{
|
||||||
|
rtc_save(arg);
|
||||||
|
file_save(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update(uev_t *w, void *arg, int events)
|
||||||
|
{
|
||||||
|
save(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
.cb = rtc_restore
|
.cb = rtc_restore
|
||||||
},
|
},
|
||||||
.hook[HOOK_SHUTDOWN] = {
|
.hook[HOOK_SHUTDOWN] = {
|
||||||
.cb = rtc_save
|
.cb = save
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -212,10 +324,14 @@ PLUGIN_INIT(plugin_init)
|
|||||||
{
|
{
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
|
|
||||||
if (!strptime(rtc_timestamp, "%Y-%m-%d %H:%M", &tm))
|
if (!strptime(rtc_timestamp, RTC_FMT, &tm)) {
|
||||||
rtc_date_fallback = mktime(&tm);
|
logit(LOG_WARNING, "Invalid restore date '%s', reverting to '%s'",
|
||||||
else
|
rtc_timestamp, RTC_TIMESTAMP_BEGIN_2000);
|
||||||
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
|
} else
|
||||||
|
rtc_date_fallback = mktime(&tm);
|
||||||
|
|
||||||
|
uev_timer_init(ctx, &rtc_timer, update, NULL, RTC_PERIOD, RTC_PERIOD);
|
||||||
|
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -154,7 +154,7 @@ static void setup(void *arg)
|
|||||||
close(fd);
|
close(fd);
|
||||||
free(rpi);
|
free(rpi);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
logit(LOG_ERR, "Failed adding entropy to kernel random pool: %s", strerror(err));
|
logit(LOG_WARNING, "Failed adding entropy to kernel random pool: %s", strerror(err));
|
||||||
print_result(rc < 0);
|
print_result(rc < 0);
|
||||||
return;
|
return;
|
||||||
fallback:
|
fallback:
|
||||||
|
|||||||
+3
-3
@@ -288,7 +288,7 @@ int cond_update(const char *name)
|
|||||||
svc_t *svc, *iter = NULL;
|
svc_t *svc, *iter = NULL;
|
||||||
int affects = 0;
|
int affects = 0;
|
||||||
|
|
||||||
dbg("%s", name);
|
// dbg("%s", name);
|
||||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||||
if (!svc_has_cond(svc) || !cond_affects(name, svc->cond))
|
if (!svc_has_cond(svc) || !cond_affects(name, svc->cond))
|
||||||
continue;
|
continue;
|
||||||
@@ -321,7 +321,7 @@ int cond_set_noupdate(const char *name)
|
|||||||
|
|
||||||
void cond_set(const char *name)
|
void cond_set(const char *name)
|
||||||
{
|
{
|
||||||
dbg("%s", name);
|
// dbg("%s", name);
|
||||||
if (cond_set_noupdate(name))
|
if (cond_set_noupdate(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ int cond_clear_noupdate(const char *name)
|
|||||||
|
|
||||||
void cond_clear(const char *name)
|
void cond_clear(const char *name)
|
||||||
{
|
{
|
||||||
dbg("%s", name);
|
// dbg("%s", name);
|
||||||
if (cond_clear_noupdate(name))
|
if (cond_clear_noupdate(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
+18
-8
@@ -1432,16 +1432,22 @@ static int conf_change_act(char *dir, char *name, uint32_t mask)
|
|||||||
strlcpy(fn, dir, sizeof(fn));
|
strlcpy(fn, dir, sizeof(fn));
|
||||||
dbg("path: %s mask: %08x", fn, mask);
|
dbg("path: %s mask: %08x", fn, mask);
|
||||||
|
|
||||||
/* Handle disabling/removal of service */
|
if (strchr(name, '@')) {
|
||||||
rp = realpath(fn, NULL);
|
/* Skip realpath for templates */
|
||||||
if (!rp) {
|
|
||||||
if (errno != ENOENT)
|
|
||||||
goto fail;
|
|
||||||
rp = strdup(fn);
|
rp = strdup(fn);
|
||||||
if (!rp)
|
} else {
|
||||||
goto fail;
|
/* Handle disabling/removal of service */
|
||||||
|
rp = realpath(fn, NULL);
|
||||||
|
if (!rp) {
|
||||||
|
if (errno != ENOENT)
|
||||||
|
goto fail;
|
||||||
|
rp = strdup(fn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!rp)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
node = conf_find(rp);
|
node = conf_find(rp);
|
||||||
if (node) {
|
if (node) {
|
||||||
dbg("event already registered for %s ...", name);
|
dbg("event already registered for %s ...", name);
|
||||||
@@ -1480,7 +1486,11 @@ int conf_changed(char *file)
|
|||||||
if (!file)
|
if (!file)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rp = realpath(file, NULL);
|
if (strchr(file, '@'))
|
||||||
|
rp = strdup(file);
|
||||||
|
else
|
||||||
|
rp = realpath(file, NULL);
|
||||||
|
|
||||||
if (!rp)
|
if (!rp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -272,8 +272,13 @@ static int fsck(int pass)
|
|||||||
* errors were corrected but that the boot may proceed.
|
* errors were corrected but that the boot may proceed.
|
||||||
*/
|
*/
|
||||||
if (fsck_rc > 1) {
|
if (fsck_rc > 1) {
|
||||||
logit(LOG_CONSOLE | LOG_ALERT, "Failed fsck %s, attempting sulogin ...", dev);
|
if (hasmntopt(mnt,"nofail")) {
|
||||||
sulogin(1);
|
logit(LOG_CONSOLE | LOG_WARNING, "Ignoring failed fsck %s because of nofail option", dev);
|
||||||
|
fsck_rc = 0;
|
||||||
|
} else {
|
||||||
|
logit(LOG_CONSOLE | LOG_ALERT, "Failed fsck %s, attempting sulogin ...", dev);
|
||||||
|
sulogin(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rc += fsck_rc;
|
rc += fsck_rc;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -87,6 +87,9 @@ void console_init(void)
|
|||||||
/* Enable line wrap, if disabled previously, e.g., qemu */
|
/* Enable line wrap, if disabled previously, e.g., qemu */
|
||||||
dprint(STDOUT_FILENO, "\033[?7h", 5);
|
dprint(STDOUT_FILENO, "\033[?7h", 5);
|
||||||
|
|
||||||
|
/* Reset atttributes, background and foreground color */
|
||||||
|
dprint(STDOUT_FILENO, "\033[49m\033[39m\e[2J", 14);
|
||||||
|
|
||||||
log_init();
|
log_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,7 +585,8 @@ int in_container(void)
|
|||||||
"lxc",
|
"lxc",
|
||||||
"docker",
|
"docker",
|
||||||
"kubepod",
|
"kubepod",
|
||||||
"unshare"
|
"unshare",
|
||||||
|
"systemd-nspawn"
|
||||||
};
|
};
|
||||||
const char *files[] = {
|
const char *files[] = {
|
||||||
"/run/.containerenv",
|
"/run/.containerenv",
|
||||||
|
|||||||
@@ -96,6 +96,12 @@ int iwatch_add1(struct iwatch *iw, char *file, uint32_t mask)
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
iwp = iwatch_find_by_path(iw, file);
|
||||||
|
if (iwp) {
|
||||||
|
dbg("skipping, %s already registered", file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fexist(file)) {
|
if (!fexist(file)) {
|
||||||
dbg("skipping %s: no such file or directory", file);
|
dbg("skipping %s: no such file or directory", file);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+107
-32
@@ -100,6 +100,9 @@ static void service_timeout_cb(uev_t *w, void *arg, int events)
|
|||||||
*/
|
*/
|
||||||
int service_timeout_after(svc_t *svc, int timeout, void (*cb)(svc_t *svc))
|
int service_timeout_after(svc_t *svc, int timeout, void (*cb)(svc_t *svc))
|
||||||
{
|
{
|
||||||
|
if (timeout == 0)
|
||||||
|
return 0; /* OK, not starting timer. */
|
||||||
|
|
||||||
if (svc->timer_cb)
|
if (svc->timer_cb)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
@@ -147,16 +150,17 @@ static void service_script_kill(svc_t *svc)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
dbg("Killing service %s script PID %d.", svc_ident(svc, NULL, 0), ptr->pid);
|
dbg("Killing service %s script PID %d.", svc_ident(svc, NULL, 0), ptr->pid);
|
||||||
kill(-ptr->pid, SIGKILL);
|
kill(ptr->pid, SIGKILL);
|
||||||
TAILQ_REMOVE(&svc_assoc_list, ptr, link);
|
TAILQ_REMOVE(&svc_assoc_list, ptr, link);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int service_script_add(svc_t *svc, pid_t pid)
|
static int service_script_add(svc_t *svc, pid_t pid, int tmo)
|
||||||
{
|
{
|
||||||
struct assoc *ptr = malloc(sizeof(*ptr));
|
struct assoc *ptr;
|
||||||
|
|
||||||
|
ptr = malloc(sizeof(*ptr));
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
err(1, "Failed starting service script timer");
|
err(1, "Failed starting service script timer");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -166,7 +170,7 @@ static int service_script_add(svc_t *svc, pid_t pid)
|
|||||||
ptr->pid = pid;
|
ptr->pid = pid;
|
||||||
TAILQ_INSERT_TAIL(&svc_assoc_list, ptr, link);
|
TAILQ_INSERT_TAIL(&svc_assoc_list, ptr, link);
|
||||||
|
|
||||||
service_timeout_after(svc, svc->killdelay, service_script_kill);
|
service_timeout_after(svc, tmo, service_script_kill);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1297,12 +1301,44 @@ static void parse_killdelay(svc_t *svc, char *delay)
|
|||||||
svc->killdelay = (int)(sec * 1000);
|
svc->killdelay = (int)(sec * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_script(char *type, char *script, char *buf, size_t len)
|
/*
|
||||||
|
* pre:[0-3600,]/path/to/script
|
||||||
|
*/
|
||||||
|
static void parse_script(svc_t *svc, char *type, char *script, int *tmo, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
if (access(script, X_OK))
|
char *found, *path;
|
||||||
logit(LOG_WARNING, "%s:%s is missing or not executable, skipping.", type, script);
|
|
||||||
else
|
path = strchr(script, ',');
|
||||||
strlcpy(buf, script, len);
|
if (path) {
|
||||||
|
const char *errstr;
|
||||||
|
long long sec;
|
||||||
|
|
||||||
|
*path++ = 0;
|
||||||
|
|
||||||
|
sec = strtonum(script, 0, 3600, &errstr);
|
||||||
|
if (errstr) {
|
||||||
|
errx(1, "%s: tmo %s is %s (0-3600)", svc_ident(svc, NULL, 0),
|
||||||
|
script, errstr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*tmo = (int)(sec * 1000);
|
||||||
|
} else {
|
||||||
|
path = script;
|
||||||
|
*tmo = svc->killdelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = which(path);
|
||||||
|
if (!found) {
|
||||||
|
/* Not in $PATH, check if path exists and is executable */
|
||||||
|
if (access(path, X_OK)) {
|
||||||
|
logit(LOG_WARNING, "%s:%s is missing or not executable, skipping.",
|
||||||
|
type, path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
free(found);
|
||||||
|
|
||||||
|
strlcpy(buf, path, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1770,15 +1806,15 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
else
|
else
|
||||||
svc->killdelay = SVC_TERM_TIMEOUT;
|
svc->killdelay = SVC_TERM_TIMEOUT;
|
||||||
if (pre_script)
|
if (pre_script)
|
||||||
parse_script("pre", pre_script, svc->pre_script, sizeof(svc->pre_script));
|
parse_script(svc, "pre", pre_script, &svc->pre_tmo, svc->pre_script, sizeof(svc->pre_script));
|
||||||
else
|
else
|
||||||
memset(svc->pre_script, 0, sizeof(svc->pre_script));
|
memset(svc->pre_script, 0, sizeof(svc->pre_script));
|
||||||
if (post_script)
|
if (post_script)
|
||||||
parse_script("post", post_script, svc->post_script, sizeof(svc->post_script));
|
parse_script(svc, "post", post_script, &svc->post_tmo, svc->post_script, sizeof(svc->post_script));
|
||||||
else
|
else
|
||||||
memset(svc->post_script, 0, sizeof(svc->post_script));
|
memset(svc->post_script, 0, sizeof(svc->post_script));
|
||||||
if (ready_script)
|
if (ready_script)
|
||||||
parse_script("ready", ready_script, svc->ready_script, sizeof(svc->ready_script));
|
parse_script(svc, "ready", ready_script, &svc->ready_tmo, svc->ready_script, sizeof(svc->ready_script));
|
||||||
else
|
else
|
||||||
memset(svc->ready_script, 0, sizeof(svc->ready_script));
|
memset(svc->ready_script, 0, sizeof(svc->ready_script));
|
||||||
if (!svc_is_tty(svc)) {
|
if (!svc_is_tty(svc)) {
|
||||||
@@ -1904,24 +1940,32 @@ void service_unregister(svc_t *svc)
|
|||||||
|
|
||||||
void service_monitor(pid_t lost, int status)
|
void service_monitor(pid_t lost, int status)
|
||||||
{
|
{
|
||||||
|
int sig = WIFSIGNALED(status);
|
||||||
|
int rc = WEXITSTATUS(status);
|
||||||
|
int ok = WIFEXITED(status);
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
if (lost <= 1)
|
if (lost <= 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* main process as well as pre: and post: scripts use svc->pid */
|
||||||
svc = svc_find_by_pid(lost);
|
svc = svc_find_by_pid(lost);
|
||||||
if (!svc) {
|
if (!svc) {
|
||||||
|
/* Check if ready: script in assoc list */
|
||||||
if (service_script_del(lost))
|
if (service_script_del(lost))
|
||||||
dbg("collected unknown PID %d", lost);
|
dbg("collected unknown PID %d", lost);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (svc->state) {
|
switch (svc->state) {
|
||||||
case SVC_CLEANUP_STATE:
|
|
||||||
case SVC_SETUP_STATE:
|
case SVC_SETUP_STATE:
|
||||||
|
/* If the setup phase fails, drive svc to crashed. */
|
||||||
|
svc->status = status;
|
||||||
|
/* fallthrough */
|
||||||
|
case SVC_CLEANUP_STATE:
|
||||||
dbg("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d",
|
dbg("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d",
|
||||||
svc->state == SVC_CLEANUP_STATE ? svc->post_script : svc->pre_script,
|
svc->state == SVC_CLEANUP_STATE ? svc->post_script : svc->pre_script,
|
||||||
lost, WIFEXITED(status), WIFSIGNALED(status), WEXITSTATUS(status));
|
lost, ok, sig, rc);
|
||||||
/* Kill all children in the same proess group, e.g. logit */
|
/* Kill all children in the same proess group, e.g. logit */
|
||||||
dbg("Killing lingering children in same process group ...");
|
dbg("Killing lingering children in same process group ...");
|
||||||
kill(-svc->pid, SIGKILL);
|
kill(-svc->pid, SIGKILL);
|
||||||
@@ -1929,7 +1973,7 @@ void service_monitor(pid_t lost, int status)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
dbg("collected %s(%d), normal exit: %d, signaled: %d, exit code: %d",
|
dbg("collected %s(%d), normal exit: %d, signaled: %d, exit code: %d",
|
||||||
svc_ident(svc, NULL, 0), lost, WIFEXITED(status), WIFSIGNALED(status), WEXITSTATUS(status));
|
svc_ident(svc, NULL, 0), lost, ok, sig, rc);
|
||||||
svc->status = status;
|
svc->status = status;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1954,10 +1998,7 @@ void service_monitor(pid_t lost, int status)
|
|||||||
service_cleanup(svc);
|
service_cleanup(svc);
|
||||||
} else if (svc_is_runtask(svc)) {
|
} else if (svc_is_runtask(svc)) {
|
||||||
/* run/task should run at least once per runlevel */
|
/* run/task should run at least once per runlevel */
|
||||||
if (WIFEXITED(status))
|
svc->started = ok;
|
||||||
svc->started = 1;
|
|
||||||
else
|
|
||||||
svc->started = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@@ -1965,7 +2006,7 @@ done:
|
|||||||
svc->start_time = svc->pid = 0;
|
svc->start_time = svc->pid = 0;
|
||||||
cont:
|
cont:
|
||||||
if (lost == run_block_pid) {
|
if (lost == run_block_pid) {
|
||||||
int result = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
|
int result = ok ? rc : 1;
|
||||||
|
|
||||||
svc_mark_clean(svc); /* done, regardless of exit status */
|
svc_mark_clean(svc); /* done, regardless of exit status */
|
||||||
run_block_pid = 0;
|
run_block_pid = 0;
|
||||||
@@ -2001,6 +2042,10 @@ static void svc_mark_affected(char *cond)
|
|||||||
* Called on conf_reload() to update service reverse dependencies.
|
* Called on conf_reload() to update service reverse dependencies.
|
||||||
* E.g., if ospfd depends on zebra and the zebra Finit conf has
|
* E.g., if ospfd depends on zebra and the zebra Finit conf has
|
||||||
* changed, we need to mark the ospfd Finit conf as changed too.
|
* changed, we need to mark the ospfd Finit conf as changed too.
|
||||||
|
*
|
||||||
|
* However, a daemon that depends on syslogd (sysklogd project), need
|
||||||
|
* not be reloeaded (SIGHUP'ed or stop/started) because syslogd support
|
||||||
|
* reloading its configuration file on SIGHUP.
|
||||||
*/
|
*/
|
||||||
void service_update_rdeps(void)
|
void service_update_rdeps(void)
|
||||||
{
|
{
|
||||||
@@ -2012,6 +2057,10 @@ void service_update_rdeps(void)
|
|||||||
if (!svc_is_changed(svc))
|
if (!svc_is_changed(svc))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Service supports reloading conf without stop/start */
|
||||||
|
if (!svc_is_nohup(svc))
|
||||||
|
continue; /* Yup, no need to stop start rdeps */
|
||||||
|
|
||||||
svc_mark_affected(mkcond(svc, cond, sizeof(cond)));
|
svc_mark_affected(mkcond(svc, cond, sizeof(cond)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2040,7 +2089,8 @@ static void service_kill_script(svc_t *svc)
|
|||||||
if (svc->pid <= 1)
|
if (svc->pid <= 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kill(-svc->pid, SIGKILL);
|
dbg("Timeout, killing service %s script PID %d", svc_ident(svc, NULL, 0), svc->pid);
|
||||||
|
kill(svc->pid, SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2051,6 +2101,9 @@ static void set_pre_post_envs(svc_t *svc, const char *type)
|
|||||||
char buf[25 + 256] = "/etc/default:/etc/conf.d";
|
char buf[25 + 256] = "/etc/default:/etc/conf.d";
|
||||||
|
|
||||||
setenv("SERVICE_TYPE", svc_typestr(svc), 1);
|
setenv("SERVICE_TYPE", svc_typestr(svc), 1);
|
||||||
|
setenv("SERVICE_NAME", svc->name, 1);
|
||||||
|
if (svc->id[0])
|
||||||
|
setenv("SERVICE_ID", svc->id, 1);
|
||||||
setenv("SERVICE_IDENT", svc_ident(svc, NULL, 0), 1);
|
setenv("SERVICE_IDENT", svc_ident(svc, NULL, 0), 1);
|
||||||
setenv("SERVICE_SCRIPT_TYPE", type, 1);
|
setenv("SERVICE_SCRIPT_TYPE", type, 1);
|
||||||
|
|
||||||
@@ -2079,6 +2132,8 @@ static void service_pre_script(svc_t *svc)
|
|||||||
};
|
};
|
||||||
char *env_file;
|
char *env_file;
|
||||||
|
|
||||||
|
redirect(svc);
|
||||||
|
|
||||||
env_file = svc_getenv(svc);
|
env_file = svc_getenv(svc);
|
||||||
if (env_file)
|
if (env_file)
|
||||||
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->pre_script);
|
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->pre_script);
|
||||||
@@ -2091,9 +2146,7 @@ static void service_pre_script(svc_t *svc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: pre:script %s started as PID %d", svc_ident(svc, NULL, 0), svc->pre_script, svc->pid);
|
dbg("%s: pre:script %s started as PID %d", svc_ident(svc, NULL, 0), svc->pre_script, svc->pid);
|
||||||
|
service_timeout_after(svc, svc->pre_tmo, service_kill_script);
|
||||||
/* Short hard-coded timeout to prevent locking up Finit */
|
|
||||||
service_timeout_after(svc, svc->killdelay, service_kill_script);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void service_post_script(svc_t *svc)
|
static void service_post_script(svc_t *svc)
|
||||||
@@ -2144,11 +2197,16 @@ static void service_post_script(svc_t *svc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: post:script %s started as PID %d", svc_ident(svc, NULL, 0), svc->post_script, svc->pid);
|
dbg("%s: post:script %s started as PID %d", svc_ident(svc, NULL, 0), svc->post_script, svc->pid);
|
||||||
|
service_timeout_after(svc, svc->post_tmo, service_kill_script);
|
||||||
/* Short hard-coded timeout to prevent locking up Finit */
|
|
||||||
service_timeout_after(svc, svc->killdelay, service_kill_script);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unlike the pre: and post: scripts, the ready: script cannot re-use
|
||||||
|
* svc->pid, so instead we use an assoc. list for matching any scripts
|
||||||
|
* related to the svc, handled by service_script_add() below. When a
|
||||||
|
* ready: script is reaped the service_monitor() checks first for the
|
||||||
|
* svc, then calls service_script_del().
|
||||||
|
*/
|
||||||
void service_ready_script(svc_t *svc)
|
void service_ready_script(svc_t *svc)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@@ -2184,9 +2242,7 @@ void service_ready_script(svc_t *svc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: ready:script %s started as PID %d", svc_ident(svc, NULL, 0), svc->ready_script, pid);
|
dbg("%s: ready:script %s started as PID %d", svc_ident(svc, NULL, 0), svc->ready_script, pid);
|
||||||
|
service_script_add(svc, pid, svc->ready_tmo);
|
||||||
/* Short hard-coded timeout to prevent locking up Finit */
|
|
||||||
service_script_add(svc, pid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void service_retry(svc_t *svc)
|
static void service_retry(svc_t *svc)
|
||||||
@@ -2439,8 +2495,27 @@ restart:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SVC_SETUP_STATE:
|
case SVC_SETUP_STATE:
|
||||||
if (!svc->pid)
|
if (!svc->pid) {
|
||||||
svc_set_state(svc, SVC_STARTING_STATE);
|
int rc = WEXITSTATUS(svc->status);
|
||||||
|
int ok = WIFEXITED(svc->status);
|
||||||
|
|
||||||
|
if (!ok || rc) {
|
||||||
|
const char *sig;
|
||||||
|
|
||||||
|
if (WIFSIGNALED(svc->status))
|
||||||
|
sig = sig_name(WTERMSIG(svc->status));
|
||||||
|
else
|
||||||
|
sig = "none";
|
||||||
|
|
||||||
|
logit(LOG_WARNING, "Service %s pre:%s failed, rc: %d sig:%s",
|
||||||
|
svc_ident(svc, NULL, 0), svc->pre_script, rc, sig);
|
||||||
|
|
||||||
|
svc_set_state(svc, SVC_STOPPING_STATE);
|
||||||
|
svc_crashing(svc);
|
||||||
|
} else {
|
||||||
|
svc_set_state(svc, SVC_STARTING_STATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SVC_WAITING_STATE:
|
case SVC_WAITING_STATE:
|
||||||
|
|||||||
@@ -169,11 +169,17 @@ void sm_init(sm_t *sm)
|
|||||||
void sm_set_runlevel(sm_t *sm, int newlevel)
|
void sm_set_runlevel(sm_t *sm, int newlevel)
|
||||||
{
|
{
|
||||||
sm->newlevel = newlevel;
|
sm->newlevel = newlevel;
|
||||||
|
|
||||||
|
dbg("Flushing pending .conf file events ...");
|
||||||
|
conf_flush_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sm_set_reload(sm_t *sm)
|
void sm_set_reload(sm_t *sm)
|
||||||
{
|
{
|
||||||
sm->reload = 1;
|
sm->reload = 1;
|
||||||
|
|
||||||
|
dbg("Flushing pending .conf file events ...");
|
||||||
|
conf_flush_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
int sm_is_in_teardown(sm_t *sm)
|
int sm_is_in_teardown(sm_t *sm)
|
||||||
|
|||||||
@@ -197,8 +197,11 @@ typedef struct svc {
|
|||||||
char desc[MAX_STR_LEN];
|
char desc[MAX_STR_LEN];
|
||||||
char env[MAX_CMD_LEN];
|
char env[MAX_CMD_LEN];
|
||||||
char pre_script[MAX_CMD_LEN];
|
char pre_script[MAX_CMD_LEN];
|
||||||
|
int pre_tmo;
|
||||||
char post_script[MAX_CMD_LEN];
|
char post_script[MAX_CMD_LEN];
|
||||||
|
int post_tmo;
|
||||||
char ready_script[MAX_CMD_LEN];
|
char ready_script[MAX_CMD_LEN];
|
||||||
|
int ready_tmo;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used to forcefully kill services that won't shutdown on
|
* Used to forcefully kill services that won't shutdown on
|
||||||
@@ -259,6 +262,7 @@ static inline int svc_is_tty (svc_t *svc) { return svc && SVC_TYPE_TTY
|
|||||||
static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type);}
|
static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type);}
|
||||||
static inline int svc_is_forking (svc_t *svc) { return svc && svc->forking; }
|
static inline int svc_is_forking (svc_t *svc) { return svc && svc->forking; }
|
||||||
static inline int svc_is_manual (svc_t *svc) { return svc && svc->manual; }
|
static inline int svc_is_manual (svc_t *svc) { return svc && svc->manual; }
|
||||||
|
static inline int svc_is_nohup (svc_t *svc) { return svc && (0 == svc->sighup); }
|
||||||
|
|
||||||
static inline int svc_in_runlevel (svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); }
|
static inline int svc_in_runlevel (svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); }
|
||||||
static inline int svc_nohup (svc_t *svc) { return svc && (0 == svc->sighup || 0 != svc->args_dirty); }
|
static inline int svc_nohup (svc_t *svc) { return svc && (0 == svc->sighup || 0 != svc->args_dirty); }
|
||||||
|
|||||||
+34
-28
@@ -1,28 +1,28 @@
|
|||||||
SUBDIRS = lib src
|
SUBDIRS = lib src
|
||||||
|
|
||||||
EXTRA_DIST = skel/bin/busybox-x86_64.sha256 skel/sbin/service.sh skel/etc/env \
|
EXTRA_DIST = skel/bin/busybox-x86_64.sha256 skel/sbin/service.sh skel/etc/env \
|
||||||
skel/bin/pre.sh skel/bin/post.sh skel/bin/ready.sh skel/bin/slay \
|
skel/bin/pre.sh skel/bin/post.sh skel/bin/ready.sh skel/bin/slay \
|
||||||
skel/sbin/fail.sh skel/usr/share/runparts/ref.log \
|
skel/sbin/fail.sh skel/usr/share/runparts/ref.log \
|
||||||
skel/usr/share/runparts/sysv.log \
|
skel/usr/share/runparts/sysv.log \
|
||||||
skel/etc/rc.d/foo.sh skel/etc/rc.d/S01abc.sh \
|
skel/etc/rc.d/foo.sh skel/etc/rc.d/S01abc.sh \
|
||||||
skel/etc/rc.d/test.sh skel/etc/rc.d/S02def.sh \
|
skel/etc/rc.d/test.sh skel/etc/rc.d/S02def.sh \
|
||||||
skel/etc/rcS.d/foo.sh skel/etc/rcS.d/test.sh \
|
skel/etc/rcS.d/foo.sh skel/etc/rcS.d/test.sh \
|
||||||
skel/etc/rcS.d/S01abc.sh skel/etc/rcS.d/S02def.sh \
|
skel/etc/rcS.d/S01abc.sh skel/etc/rcS.d/S02def.sh \
|
||||||
skel/cdrom/.empty skel/dev/shm/.empty skel/dev/pts/.empty \
|
skel/cdrom/.empty skel/dev/shm/.empty skel/dev/pts/.empty \
|
||||||
skel/etc/inittab skel/etc/hostname skel/etc/fstab \
|
skel/etc/inittab skel/etc/hostname skel/etc/fstab \
|
||||||
skel/etc/init.d/rcS skel/etc/init.d/rcK skel/tmp/.empty \
|
skel/etc/init.d/rcS skel/etc/init.d/rcK skel/tmp/.empty \
|
||||||
skel/etc/finit.d/.empty skel/etc/finit.d/available/.empty \
|
skel/etc/finit.d/.empty skel/etc/finit.d/available/.empty \
|
||||||
skel/etc/finit.d/enabled/.empty \
|
skel/etc/finit.d/enabled/.empty \
|
||||||
skel/sbin/task.sh skel/bin/crasher.sh \
|
skel/sbin/task.sh skel/bin/crasher.sh skel/bin/fail.sh \
|
||||||
skel/etc/init.d/S01-service.sh skel/etc/init.d/S02-serv.sh \
|
skel/etc/init.d/S01-service.sh skel/etc/init.d/S02-serv.sh \
|
||||||
skel/proc/.empty skel/root/.empty skel/run/.empty \
|
skel/proc/.empty skel/root/.empty skel/run/.empty \
|
||||||
skel/sbin/chrootsetup.sh skel/srv/.empty skel/sys/.empty \
|
skel/sbin/chrootsetup.sh skel/srv/.empty skel/sys/.empty \
|
||||||
skel/usr/bin/.empty skel/usr/lib/.empty skel/usr/sbin/.empty \
|
skel/usr/bin/.empty skel/usr/lib/.empty skel/usr/sbin/.empty \
|
||||||
skel/home/.empty skel/usr/games/.empty skel/usr/src/.empty \
|
skel/home/.empty skel/usr/games/.empty skel/usr/src/.empty \
|
||||||
skel/usr/share/.empty skel/usr/include/.empty \
|
skel/usr/share/.empty skel/usr/include/.empty \
|
||||||
skel/usr/local/games/.empty skel/usr/local/sbin/.empty \
|
skel/usr/local/games/.empty skel/usr/local/sbin/.empty \
|
||||||
skel/usr/local/share/.empty skel/usr/local/src/.empty \
|
skel/usr/local/share/.empty skel/usr/local/src/.empty \
|
||||||
skel/usr/local/lib/.empty skel/usr/local/bin/.empty \
|
skel/usr/local/lib/.empty skel/usr/local/bin/.empty \
|
||||||
skel/usr/local/etc/.empty skel/var/.empty
|
skel/usr/local/etc/.empty skel/var/.empty
|
||||||
|
|
||||||
EXTRA_DIST += setup-sysroot.sh
|
EXTRA_DIST += setup-sysroot.sh
|
||||||
@@ -40,6 +40,7 @@ EXTRA_DIST += initctl-status-subset.sh
|
|||||||
EXTRA_DIST += notify.sh
|
EXTRA_DIST += notify.sh
|
||||||
EXTRA_DIST += pidfile.sh
|
EXTRA_DIST += pidfile.sh
|
||||||
EXTRA_DIST += pre-post-serv.sh
|
EXTRA_DIST += pre-post-serv.sh
|
||||||
|
EXTRA_DIST += pre-fail.sh
|
||||||
EXTRA_DIST += process-depends.sh
|
EXTRA_DIST += process-depends.sh
|
||||||
EXTRA_DIST += rclocal.sh
|
EXTRA_DIST += rclocal.sh
|
||||||
EXTRA_DIST += ready-serv.sh
|
EXTRA_DIST += ready-serv.sh
|
||||||
@@ -65,11 +66,6 @@ AM_TESTS_ENVIRONMENT += export LD_LIBRARY_PATH;
|
|||||||
AM_TESTS_ENVIRONMENT += top_builddir=$(top_builddir);
|
AM_TESTS_ENVIRONMENT += top_builddir=$(top_builddir);
|
||||||
AM_TESTS_ENVIRONMENT += export top_builddir;
|
AM_TESTS_ENVIRONMENT += export top_builddir;
|
||||||
|
|
||||||
checkself.sh:
|
|
||||||
@echo '#!/bin/sh' > $@
|
|
||||||
@echo shellcheck $(addprefix '"$$srcdir"'/,$(filter %.sh,$(filter-out $@, $(TESTS)))) >> $@
|
|
||||||
@chmod +x $@
|
|
||||||
|
|
||||||
TEST_EXTENSIONS = .sh
|
TEST_EXTENSIONS = .sh
|
||||||
TESTS = checkself.sh
|
TESTS = checkself.sh
|
||||||
TESTS += add-remove-dynamic-service.sh
|
TESTS += add-remove-dynamic-service.sh
|
||||||
@@ -86,6 +82,7 @@ TESTS += initctl-status-subset.sh
|
|||||||
TESTS += notify.sh
|
TESTS += notify.sh
|
||||||
TESTS += pidfile.sh
|
TESTS += pidfile.sh
|
||||||
TESTS += pre-post-serv.sh
|
TESTS += pre-post-serv.sh
|
||||||
|
TESTS += pre-fail.sh
|
||||||
TESTS += process-depends.sh
|
TESTS += process-depends.sh
|
||||||
TESTS += rclocal.sh
|
TESTS += rclocal.sh
|
||||||
TESTS += ready-serv.sh
|
TESTS += ready-serv.sh
|
||||||
@@ -109,6 +106,15 @@ TESTS += unexpected-restart.sh
|
|||||||
|
|
||||||
check-recursive: setup-chroot
|
check-recursive: setup-chroot
|
||||||
|
|
||||||
|
.PHONY: checkself.sh
|
||||||
|
checkself.sh:
|
||||||
|
@echo '#!/bin/sh' > $@
|
||||||
|
@echo 'set -eu' >> $@
|
||||||
|
@echo 'cd "$$srcdir" 2>/dev/null || cd "." || exit 1' >> $@
|
||||||
|
@echo 'TESTS="$(filter %.sh,$(filter-out $@, $(TESTS)))"' >> $@
|
||||||
|
@echo 'shellcheck $$TESTS' >> $@
|
||||||
|
@chmod 0755 $@
|
||||||
|
|
||||||
.PHONY: setup-chroot
|
.PHONY: setup-chroot
|
||||||
setup-chroot:
|
setup-chroot:
|
||||||
@SYSROOT='$(abs_builddir)/sysroot/' srcdir=$(srcdir) top_builddir=$(top_builddir) $(srcdir)/setup-sysroot.sh
|
@SYSROOT='$(abs_builddir)/sysroot/' srcdir=$(srcdir) top_builddir=$(top_builddir) $(srcdir)/setup-sysroot.sh
|
||||||
|
|||||||
+3
-2
@@ -27,15 +27,16 @@ test_teardown()
|
|||||||
say "Waiting for runlevel 2"
|
say "Waiting for runlevel 2"
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
#run "initctl debug"
|
run "initctl debug"
|
||||||
|
|
||||||
say "Add service stanza to $FINIT_CONF ..."
|
say "Add service stanza to $FINIT_CONF ..."
|
||||||
run "echo 'service serv -np -e foo:bar -- Verify foo=bar' >> $FINIT_CONF"
|
run "echo 'service serv -np -e foo:bar -- Verify foo=bar' >> $FINIT_CONF"
|
||||||
#run "cat $FINIT_CONF"
|
run "cat $FINIT_CONF"
|
||||||
|
|
||||||
say 'Reload Finit'
|
say 'Reload Finit'
|
||||||
run "initctl reload"
|
run "initctl reload"
|
||||||
sleep 1
|
sleep 1
|
||||||
|
run "initctl"
|
||||||
retry 'assert_num_children 1 serv'
|
retry 'assert_num_children 1 serv'
|
||||||
|
|
||||||
say "Modify $FINIT_CONF slightly ..."
|
say "Modify $FINIT_CONF slightly ..."
|
||||||
|
|||||||
@@ -84,6 +84,14 @@ assert_status()
|
|||||||
assert "Service $service $status" "$(texec initctl -p status "$service" | awk '/Status/{print $3}')" = "$status"
|
assert "Service $service $status" "$(texec initctl -p status "$service" | awk '/Status/{print $3}')" = "$status"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Used by, e.g., pre-fail.sh
|
||||||
|
assert_status_full()
|
||||||
|
{
|
||||||
|
service=$1; shift
|
||||||
|
status="$*"
|
||||||
|
assert "Service $service status is: $status" "$(texec initctl -p status "$service" | awk '/Status/{sub("^ *Status : ", ""); print}')" = "$status"
|
||||||
|
}
|
||||||
|
|
||||||
assert_cond()
|
assert_cond()
|
||||||
{
|
{
|
||||||
cond=$1
|
cond=$1
|
||||||
|
|||||||
Executable
+28
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Verify Finit:
|
||||||
|
# - does not start main process when pre:script fails
|
||||||
|
# - times out and kills long running pre:script
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
#export DEBUG=true
|
||||||
|
TEST_DIR=$(dirname "$0")
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$TEST_DIR/lib/setup.sh"
|
||||||
|
|
||||||
|
vrfy()
|
||||||
|
{
|
||||||
|
nm=serv
|
||||||
|
tmo=$1
|
||||||
|
msg=$2
|
||||||
|
err=$3
|
||||||
|
|
||||||
|
run "echo 'service [2345] pre:$tmo,fail.sh $nm -n -- $msg' > $FINIT_CONF"
|
||||||
|
run "initctl reload"
|
||||||
|
|
||||||
|
retry "assert_status_full $nm 'crashed $err'" 50
|
||||||
|
}
|
||||||
|
|
||||||
|
#run "initctl debug"
|
||||||
|
|
||||||
|
vrfy 5 "Failing pre: script" "(code=exited, status=42)"
|
||||||
|
vrfy 1 "Timeout pre: script" "(code=signal, status=9/KILL)"
|
||||||
@@ -42,8 +42,8 @@ test_one()
|
|||||||
|
|
||||||
sep
|
sep
|
||||||
say "Add stanza to $FINIT_CONF"
|
say "Add stanza to $FINIT_CONF"
|
||||||
run "echo 'run fail.sh -- Failure' > $FINIT_RCSD/fail.conf"
|
run "echo 'run /sbin/fail.sh -- Failure' > $FINIT_RCSD/fail.conf"
|
||||||
run "echo 'run initctl touch fail' > $FINIT_RCSD/touch.conf"
|
run "echo 'run initctl touch fail' > $FINIT_RCSD/touch.conf"
|
||||||
test_one 2
|
test_one 2
|
||||||
|
|
||||||
sep
|
sep
|
||||||
|
|||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
exit 42
|
||||||
+2
-1
@@ -10,7 +10,8 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
TEST_DIR=$(dirname "$0")
|
TEST_DIR=$(dirname "$0")
|
||||||
#DEBUG=1
|
# shellcheck disable=2034
|
||||||
|
DEBUG=1
|
||||||
|
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
BOOTSTRAP="runparts sysv /etc/rcS.d"
|
BOOTSTRAP="runparts sysv /etc/rcS.d"
|
||||||
|
|||||||
Reference in New Issue
Block a user