Commit Graph
77 Commits
Author SHA1 Message Date
Joachim Wiberg d22dea74e3 Finalize refactor to new log macros, following-up to 37e3be9
This possible also mitigates the issue tracked in #307.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-10-09 12:52:40 +02:00
Joachim Wiberg e589c5b269 Refactor, create svc_find_by_cond() from api.c callback
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-08-18 14:00:02 +02:00
Joachim Wiberg 35400f2a8b Minor, drop unused header file
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-15 10:36:47 +02:00
Joachim Wiberg d3c6351ed8 Fix nasty service matcher bug
In some conditions, typically when the same command is used for multiple
services, e.g. the modules-load plugin, the svc_find() function returned
an existing "similar" entry instead of NULL, causing loss of config.

When creating, and searching for, a run/task/service we must follow the
new name:id paradigm to the letter.  Always create based on name:id and
always search for matching name:id.  The name may be derived from the
command, but they cannot be used interchangably.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-06 07:57:08 +02:00
Joachim Wiberg 181d9556a1 Drop config.h include from helpers.h, exported header file
Drop the config.h include from helpers.h after a report from a colleague
trying to build an external plugin from the latest GIT sources.

Instead, make sure config.h is included, and properly commented, in all
.c files that have configure #ifdefs and other deps.  Also, move more
ot the includes from helpers.h to their respective .c file instead to
reduce the amount of headers an external plugin pulls in.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-05-05 14:48:30 +02:00
Joachim Wiberg 108bbf56dd Update copyright years
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-04-19 19:35:49 +02:00
Joachim Wiberg 10577f3e48 Allow matching of svc_t and pid file, prefer PID over file lookup
When a SysV init script starts a daemon, Finit knows nothing of the PID
it should monitor.  The PID is written, by start-stop-daemon or the
daemon itself, to the PID file.  Finit monitors for new PID files and
can match the PID in such files with an svc_t.

For the regular use-case, we prefer first looking up the matching svc_t
based on the PID -- assuming we start and monitor the service.  As a
fallback we resort to mathching the svc_t's declared PID file with the
new file we just discovered.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-03-25 06:53:59 +01:00
Jörgen Sigvardsson 4121113688 Added implementation for the new command INIT_CMD_SIGNAL.
The implementation looks up the named service by using
`svc_parse_jobstr`. The callbacks for `svc_parse_jobstr` has been
augmented to accept a user data parameter. For this use case,
a carrier for the actual signal was needed. The address of the
signal parameter is taken and passed on as a `void *`. The
callback then simply deferences it as an int - the signal number.
2022-02-15 12:29:40 +01:00
Ming Liu cfffcd4513 svc.c: change strncmp to string_compare
strncmp can not handle the case when name is a substring of cmd.

Signed-off-by: Ming Liu <liu.ming50@gmail.com>
2022-02-05 13:54:54 +01:00
Joachim Wiberg b53f2f4a60 Cleanup, drop now unused internal function svc_is_unique()
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-01-02 05:34:10 +01:00
Joachim Wiberg 280d91b9bf Add support for new libite (-lite) header namespace
Due to an unfortunate name clash with the DirectFB project LiTE, the
libite (-lite) project had to change its header namespace from

   lite/*.h -> libite/*.h

This patch adds support for the new namepace in Finit, triggered by the
define _LIBITE_LITE, from the .pc file read by pkg-config.  This should
only be needed on systems that install libite without the compatibility
symlink lite -> libite/ in the staging include directory.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-12-06 21:38:20 +01:00
Joachim Wiberg 266e5b30eb Drop all mention of old fallback shell from comments
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-04-25 21:43:16 +02:00
Joachim Wiberg 7f76202865 Simplify, drop --enable-fallback-shell from configure script
Recommend using `notty` option in tty stanza instead.  See the updated
docs for details.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-04-18 23:13:19 +02:00
Joachim Wiberg 4f40b65f0c svc_find_by_tty(): fix finder fn, check svc->dev, not name
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-04-15 08:46:21 +02:00
Joachim Wiberg 4bb67bc06f Restore @console handling and support for external getty
- Drop vhangup(), how did things ever work *with* this in?!
 - setsid() + TIOCSCTTY are best buds, see notty code
 - Allow storing any non-NULL string as tty->dev, expand in service_register()
 - Reorder parse_cmdline_args(), we need to expand @console to current dev
 - Fix tty arg parser, swapparoo for external getty
 - Refactor tty_atcon(), iterated over by service_register()
 - New arg format, need to translate for old run_getty2()

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-04-14 23:41:22 +02:00
Joachim Wiberg c0368d2b16 Refactor fallback shell handling, run as regular service
This patch re-enables the fallback shell handling after the big TTY
refactor.  We do this by allowing the fallback shell to run as a
regular service.

Note: this also adds the "hidden" support for 'notty' option for
      tty configurations stanzas.  This is just to pick up from
      where the kernel left us, reusing stdin + stdout.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-04-14 16:29:19 +02:00
Joachim Wiberg 30020263ba Refactor tty handling to use service backend enabling conditions etc.
Initial refactor of the tty implementation to use the service/run/task
general backend.  This enables all the features of services also for
ttys, except logging because it makes no sense.

Work in progress:

 - plugins/tty.c does not work anymore, could possibly be removed in
   favor of usinga (a new) condition instead (if-tty-exists)
 - fallback tty does not work anymore, should we remove it, or can we
   handle it as an optional built-in with (a new) condition?
 - @console does not work anymore, needs to generate N cloned services

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-04-14 16:29:19 +02:00
Jacques de Laval 10f4c7fa18 Do a full restart rather than HUP if command line of a service has changed
By keeping track of when a full restart is needed, Finit can relieve
the user of having to track modifications to service configuration. This
also makes initctl reload easier to explain and reason about as the effect
of a reload should now be that any configuration updates to services will
be fully "commited" by initctl reload.

Signed-off-by: Jacques de Laval <Jacques.De.Laval@westermo.com>
2021-04-01 16:18:54 +02:00
Joachim Wiberg 3ad4f6ef4b In garbage collect, don't clear conditions provided by new instances
Sneaky bug, when switching between different sets of configurations, a
new instance of a previously removed svc can have its condition removed
by svc_gc() of the old instance.  This patch prevents such accidents.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-20 14:27:01 +01:00
Joachim Wiberg 4170a61d0b Merge pull request #160 from troglobit/release
Forward port dirty vs enabled fixes from release branch
2021-03-19 17:23:36 +01:00
Jacques de Laval b3fad1077e Store removal status separate from dirty
Having removal status stored in the dirty status resulted in removal
status being forgotten when a service was marked as dirty, for instance
when a dependency was updated. This side effect of marke_dirty seems a bit
unexpected and instead of adding exceptions to the logic for when marking
a service dirty - let's separate the two things (dirty and removed) from each
other.

Signed-off-by: Jacques de Laval <Jacques.De.Laval@westermo.com>
2021-03-19 16:53:04 +01:00
Joachim Wiberg 74d715243c sanitize(): avoid strlen() to check string for NUL termination
The strlen() function can easiliy go out of bounds.  Use memchr()
instead, we have the max buffer len as argument anyway.

Also fix call to sanitize() which used wrong length.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-18 18:23:50 +01:00
Joachim Wiberg 280608f30e plugins: pidfile: track PID file in svc, if svc has none declared
Services that create their own PID files usually don't declare one with
Finit.  This patch adds support to track those PID files anywayt at
runtime for the purpose of identifying match svc_t when a PID file is
removed, i.e. when a service exits.

 - On IN_CREATE the pidfile.so plugin saves the pid file name in svc_t
 - On ON_DELETE the pidfile.so plugin finds svc_t based on pid file

Quicker tracking and less dead code, win-win.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-11 21:56:49 +01:00
Joachim Wiberg 11a3318c02 Properly set status 'missing' for missing binaries and/or env files
When we try to start a service/run/task we call whichp() to see if the
binary exists, either tha absolute path given in the .conf file, or in
the $PATH we run with.  If binary, or the env: file, doesn't exist we
now set svc_missing() state.

On `initctl reload` we unblock the service to be able to check again.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-11 11:44:23 +01:00
Joachim Wiberg 2711b27971 plugins: pidfile: tricky zebra doesn't close its pid file
This patch fixes a few really hard problems wrt PID files:

 1. Listening for IN_CREATE events means we get notified immediately by
    the kernel when someone calls open()/fopen() on a PID file.  Reading
    the contents returns 0, thank you atoi() ... so we drop IN_CREATE
    and instead look for IN_CLOSE_WRITE, there fixed it!  Not quite ...

 2. Some programs, like Zebra, and other Quagga/Frr daemons, don't
    close() their PID files after creation.  Instead they ftruncate()
    and keep them open, and locked.  Presumably to get a mechanism to
    detect already running instances -- messes life up a bit for the
    rest of us though.  So we need to read files after IN_MODIFY too.

 3. We also want to track IN_DELETE so we can deassert conditions when
    services exit gracefully and clean up their PID files

The rest fo the commit is debug instrumentation changes.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-11 11:44:23 +01:00
Joachim Wiberg dd6ebc3b65 Drop svc pidfile matching, only match against PID in pidfile
With the redesign from <svc/path/to/pidfile> to <pid/name:id> in d1fac6f
we moved to matching svc_t only against their PID, which could pop up in
any *.pid or */pid in /var/run.  This patch drops the (hopefully) last
remnants of the old <svc/> legacy.

To ensure we don't try reading the PID value from socket files, like
/var/run/initctl, we add simple fnmatch() of the inotified file.  Two
calls to fnmatch(), for portability reasons, not every system has GNU
libc extensions like FNM_EXTMATCH.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-23 20:26:57 +01:00
Joachim Wiberg 5fbcf6814c Warn if a new service asserts the same condition as an existing one
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-13 12:07:20 +01:00
Joachim Wiberg e88a9b14ff Fix #101: remove built-in inetd from finit
This patch removes the built-in inetd support from Finit.  We recommend
using an external inetd instead, e.g. xinetd.

If you liked the feature set our inetd provided; filtering per interface
and port redirection, then please let us know or use the code in this
patch (MIT licensed) to recreate it.  We are open to reintroducing it,
but then as a stand-alone daemon like the bundled watchdogd and getty.

So long for now, old friend.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-11 12:46:40 +01:00
Joachim Wiberg a5714a058c Update copyright years
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-09 22:07:03 +01:00
Joachim Wiberg 24a78d3246 Update copyright years and author last name
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2020-09-02 23:38:11 +02:00
Joachim Nilsson 3b63946973 svc: The 'id' is optional now, lets default it to "" if unset
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-05-03 12:00:28 +02:00
Joachim Nilsson 83078d1947 Ignore ENOENT from realpath(), origin probably moved
The svc_find_by_pidfile() function is called async from the pidfile
plugin, so by the time the queue is processed the origin may have
moved or been removed even.  Safe to ignore.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-26 21:46:24 +02:00
Joachim Nilsson 8fe4aad53e Make run/task/service :ID optional, default to zero/NULL
This patch makes the ':ID' field optional when registering non-inetd
run/taks/service etc.  It has always been optional in the .conf files,
but internally we defaulted to ':1'.

To open up for more useful conditions we now default to zero/NULL :ID,
meaning the user now *must* keep track of the :ID field if they have
multiple services with the same name.  This should already have been
an issue since such services would likely have conflicted with their
PID files (same name).  So it's unlikely to affect any user severely.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-23 15:21:28 +02:00
Joachim Nilsson cfa97253be Fix missing signal.h, required when building for uClibc
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-22 22:34:19 +02:00
Joachim Nilsson af45166814 src: Add critical debug messages for debugging condition handling
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-22 21:15:48 +02:00
Joachim Nilsson 6306c757a2 src: svc: Use realpath() to check if untangled file exists
The svc_find_by_pidfile() function may be called with "/run/./foo.pid",
or similar, which must be sanitized before being compared to the PID
file of each svc_t.

This patch introduce realpath() to untangle the paths and check if the
file actually exists.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-22 21:15:48 +02:00
Joachim Nilsson 3865ce765e src: svc: Handle case where multiple services have same PID file
Services may exist in multiple runlevels, i.e. one behavior at bootstrap
and another at runtime.  If the user does not set a specific PID file to
be used as condition finit can match the wrong svc.

This patch extends svc_find_by_pidfile() to also compare the contents of
the PID file with the PID of the registered svc_t.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-22 21:15:48 +02:00
Joachim Nilsson 54cfa74042 Fix #109: Support PID files in subdirectories to /var/run
Services, like dbus and teamd for instance, may create their PID files
in a subdirectory of /var/run (today often /run). E.g.,

   - /var/run/teamd/a1.pid    -- For aggregate A1
   - /var/run/dbus/pid
   - /var/run/lxc/foo.pid     -- For container foo

This patch adds support for dynamically adding inotify watchers to any
new subdirectory created in /var/run (discarding too deep directories).

To match services in this directory the run/task/service/sysv stanza
must contain the pid:!/path/to/pidfile.pid syntax.  This pid file name
is also used to create the condition this service asserts using the
following formula:

   svc/ + <dirname of service> + <subdir and file without .pid>

E.g., the case of teamd (above) gives condition 'svc/usr/bin/teamd/a1'

The special case of dbus is interesting, since it may not be a special
case, but rather the norm for services using a subdirectory.  It is
handled as follows; when a new subdirectory is detected, the directory
is scanned for files matching *.pid.  Matching files follow the teamd
case.  The directory is also scanned for 'pid', which then gives us the
condition 'svc/usr/bin/dbus'

One last example, illustrated by lxc-start, where we want to track the
condition for the LXC container foo.  The service stanza:

   service pid:!/run/lxc/foo.pid lxc-start -n foo -F -p /run/lxc/foo.pid -- Container foo

This command has no leading path so the condition is composed entirely
from the PID file location:

   svc/  + '' + lxc/foo => svc/lxc/foo

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-28 16:39:53 +01:00
Joachim Nilsson b66069278f Support for a custom kill:DELAY, default 3 sec
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-26 18:49:47 +01:00
Joachim Nilsson 1192506d43 Support for custom halt:signal, default SIGTERM
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-26 18:28:02 +01:00
Jonas Holmberg a19a3c774e Fix issue where svc_find() finds the wrong service
This issue may arise in situations where the name of the service being
compared is a sub-string of the service we want to see if it exist.

Example:
  - Two different services: teamd, teamdagentd
  - They have the same id, 1 being the default if none is specified
  - The service with the shortest name is created first

While checking if the "teamdagentd" service exists we eventually compare
it to the "teamd" service.  Prior to this fix we only compare the names
names with the length of the existing service.  Hence, teamdagentd will
seem to be the same as teamd since the first part of the string is equal
to the existing.

Signed-off-by: Jonas Holmberg <jonas.holmberg@westermo.se>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-01-07 13:23:53 +01:00
Joachim Nilsson a4f1330eae Simplify, no need to check svc->id, is always a valid string
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-01-07 13:21:46 +01:00
Joachim Nilsson b369e1cfa2 Refactor svc_parse_jobstr(), use tokstr() instead of strtok_r()
This is a safer version of strtok() that makes sure we do not step
outside of string bounds.  Coverity complained about this, but was
likely more concerned with the lacking sanitize() and trusting data
read from a UNIX domain socket ...

Note: not only is tokstr() not re-entrant, it is also hard-coded
      to only check for whitespace as token separator.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-01-07 02:51:15 +01:00
Joachim Nilsson 7fc515678f Check if svc ID is non-empty before strcmp(), found by Coverity
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-01-06 21:31:04 +01:00
Jonas Johansson f5f1a55747 Add support to specify service ID as a string
Signed-off-by: Jonas Johansson <jonasj76@gmail.com>
2018-12-11 16:43:05 +01:00
Robert Andersson d371b85c47 fix C++ compilation issues
Signed-off-by: Robert Andersson <robert.m.andersson@se.atlascopco.com>
2018-10-22 12:51:58 +02:00
Robert Andersson f2cab53e55 Add service/task name config option
Allows the service/task name derived from the binary to be
overridden with a custom name.

Example:
    service name:dhcpd [2] /usr/sbin/udhcpd -f -- DHCP Server

Signed-off-by: Robert Andersson <robert.m.andersson@se.atlascopco.com>
2018-10-22 12:51:58 +02:00
Joachim Nilsson 4870cab898 Refactor, use new work queue helper
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-10-07 21:30:07 +02:00
Joachim Nilsson 46683f8eb8 Remove service condition when service is deleted
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-10-04 21:56:01 +02:00
Joachim Nilsson cb9f6213dc Instead of deleting svc_t, mark it for cleanup by garbage collector
When a process, that has been sent SIGTERM by us, takes a full 3 sec to
terminate, the event loop may have both the SIGCHLD event (where we do
the svc_del()) and the 3 sec timeout event to send SIGKILL in its event
cache.

When we call svc_del() it releases the svc_t memory, which can then be
dereferenced by the SIGKILL timer callback and we're doomed.

There are two fixes to this; 1) the event loop, that uses epoll_wait(),
can set maxevents=1 (instead of today's 10).  The kernel will then drop
the SIGKILL timer event before it's delivered to the userspace process.
2) we can postpone deleting the svc_t to a "later stage" when all events
in the event cache have been processed.

This patch implements (2).  A later patch will use uev_init1(ctx, 1) to
ensure the event cache handles only one event at a time.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-10-02 13:22:21 +02:00