Commit Graph

128 Commits

Author SHA1 Message Date
Luca Boccassi
47dba9fb09 path unit: add TriggerLimitBurst= and TriggerLimitIntervalSec=
Given there's now a default for these settings, also allow users to configure
them, matching socket units
2021-12-18 23:17:53 +00:00
Daan De Meyer
aaae822b37 core: Add trigger limit for path units
When conditions fail on a service unit, a path unit can cause
PID 1 to busy loop as it keeps trying to activate the service unit.
To avoid this from happening, add a trigger limit to the path unit,
identical to the trigger limit we have for socket units.

Initially, let's start with a high limit and not make it configurable.
If needed, we can add properties to configure the rate limit similar
to the ones we have for socket units.
2021-12-18 11:26:25 +01:00
Daan De Meyer
40f41f34d4 Revert "core: Propagate condition failed state to triggering units."
This reverts commit 12ab94a1e4.
2021-12-17 19:39:29 +01:00
yangmingtai
5896a9ebdb fix DirectoryNotEmpty when it comes to a Non-directory file 2021-12-07 01:28:07 +09:00
Yu Watanabe
8add30a03c tree-wide: use ERRNO_IS_TRANSIENT() 2021-11-30 23:06:43 +09:00
Lennart Poettering
35cd0ba516 shared: clean up mkdir.h/label.h situation
Previously the mkdir_label() family of calls was implemented in
src/shared/mkdir-label.c but its functions partly declared ins
src/shared/label.h and partly in src/basic/mkdir.h (!!). That's weird
(and wrong).

Let's clean this up, and add a proper mkdir-label.h matching the .c
file.
2021-11-16 17:03:28 +01:00
Michal Sekletar
705578c3b9 core: rename/generalize UNIT(u)->test_start_limit() hook
Up until now the main reason why we didn't proceed with starting the
unit was exceed start limit burst. However, for unit types like mounts
the other reason could be effective ratelimit on /proc/self/mountinfo
event source. That means our mount unit state may not reflect current
kernel state. Hence, we need to attempt to re-run the start job again
after ratelimit on event source expires.

As we will be introducing another reason than start limit let's rename
the virtual function that implements the check.
2021-11-11 17:04:36 +01:00
Daan De Meyer
12ab94a1e4 core: Propagate condition failed state to triggering units.
Alternative to https://github.com/systemd/systemd/pull/20531.

Whenever a service triggered by another unit fails condition checks,
stop the triggering unit to prevent systemd busy looping trying to
start the triggered unit.
2021-11-03 20:25:14 +00:00
Lennart Poettering
9e5fd71799 basic: split out inotify-related calls from fs-util.h → inotify-util.h 2021-10-05 16:14:37 +02:00
Daan De Meyer
9727f2427f core: Check unit start rate limiting earlier
Fixes #17433. Currently, if any of the validations we do before we
check start rate limiting fail, we can still enter a busy loop as
no rate limiting gets applied. A common occurence of this scenario
is path units triggering a service that fails a condition check.

To fix the issue, we simply move up start rate limiting checks to
be the first thing we do when starting a unit. To achieve this,
we add a new method to the unit vtable and implement it for the
relevant unit types so that we can do the start rate limit checks
earlier on.
2021-08-25 13:26:14 +01:00
Zbigniew Jędrzejewski-Szmek
48d83e3368 core: align string tables 2021-07-19 11:33:52 +02:00
Zbigniew Jędrzejewski-Szmek
e437538f35 tree-wide: make cunescape*() functions return ssize_t
Strictly speaking, we are returning the size of a memory chunk of
arbitrary size, so ssize_t is more appropriate than int.
2021-07-09 15:07:40 +02:00
Zbigniew Jędrzejewski-Szmek
9faf12110a Merge pull request #20030 from keszybz/exec_fd-event-source
exec_fd event source rework
2021-07-01 08:57:23 +02:00
Lennart Poettering
41cdcb5498 core: watch paths with symlinks in .path units
When watching paths that contain symlinks in some element we so far
always only watched the inode they are pointing to, not the symlink
inode itself. Let's fix that and always watch both. We do this by simply
installing the inotify watch once with and once without IN_DONT_FOLLOW.
For non-symlink inodes this just overrides the same watch twice (where
the second one replaces the first), which is has no effect effectively.
For symlinks it means we'll watch both source and destination.

Fixes: #17727
2021-05-25 23:14:38 +02:00
Lennart Poettering
d6d00b650f core: optimize loop in path_spec_fd_event()
Let's avoid the whole loop if it can never match
2021-05-25 23:14:34 +02:00
Lennart Poettering
795125cd11 core: log about all errors in path_spec_watch()
So far we logged about most, but not all errors. Adding log to all
errors.
2021-05-25 23:14:30 +02:00
Lennart Poettering
44ff2a5e9c core: align path inotify mask table a bit 2021-05-25 23:13:52 +02:00
Zbigniew Jędrzejewski-Szmek
5dcadb4c83 core: disable event sources before unreffing them
This mirrors the change done for systemd-resolved in
9793530228. Quoting that patch:

> We generally operate on the assumption that a source is "gone" as soon as we
> unref it. This is generally true because we have the only reference. But if
> something else holds the reference, our unref doesn't really stop the source
> and it could fire again.

In particular, we take temporary references from sd-event code, and when called
from an sd-event callback, we could temporarily see this elevated reference
count. This patch doesn't seem to change anything, but I think it's nicer to do
the same change as in other places and not rely on _unref() immediately
disabling the source.
2021-05-12 12:08:52 +02:00
Lennart Poettering
bc32241e6a core: use UNIT_TRIGGER at more places
Just some minor simplification.
2021-04-15 20:38:20 +01:00
Yu Watanabe
d85ff94477 core: use SYNTHETIC_ERRNO() macro 2020-11-27 14:35:20 +09:00
Yu Watanabe
db9ecf0501 license: LGPL-2.1+ -> LGPL-2.1-or-later 2020-11-09 13:23:58 +09:00
Lennart Poettering
47ab8f73e3 core: propagate unit start limit hit state to triggering path unit
We already do this for socket and automount units, do it for path units
too: if the triggered service keeps hitting the start limit, then fail
the triggering unit too, so that we don#t busy loop forever.

(Note that this leaves only timer units out in the cold for this kind of
protection, but it shouldn't matter there, as they are naturally
protected against busy loops: they are scheduled by time anyway).

Fixes: #16669
2020-09-14 13:05:09 +02:00
Lennart Poettering
0377cd2936 core: propagate triggered unit in more load states
In 4c2ef32767 we enabled propagating
triggered unit state to the triggering unit for service units in more
load states, so that we don't accidentally stop tracking state
correctly.

Do the same for our other triggering unit states: automounts, paths, and
timers.

Also, make this an assertion rather than a simple test. After all it
should never happen that we get called for half-loaded units or units of
the wrong type. The load routines should already have made this
impossible.
2020-09-14 13:05:09 +02:00
Zbigniew Jędrzejewski-Szmek
98506a41fe Merge pull request #15697 from OhNoMoreGit/fix-path-units
Recheck PathExists=, PathExistsGlob=, DirectoryNotEmpty= when triggered unit terminates
2020-06-25 18:23:47 +02:00
Zbigniew Jędrzejewski-Szmek
23450c897d core: fix compilation with gcc -O3
../src/core/path.c: In function ‘path_serialize’:
../src/core/path.c:616:24: error: ‘%s’ directive argument is null [-Werror=format-overflow=]
  616 |                 (void) serialize_item_format(f, "path-spec", "%s %%i %%s",
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  617 |                                              path_type_to_string(s->type) //,
      |                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  618 |                                              //                                             s->previous_exists,
      |                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  619 |                                              //                                             s->path
      |                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  620 |                 );
      |                 ~
In function ‘path_spec_dump’,
    inlined from ‘path_dump’ at ../src/core/path.c:392:17:
../src/core/path.c:226:9: error: ‘%s’ directive argument is null [-Werror=format-overflow=]
  226 |         fprintf(f,
      |         ^~~~~~~~~~
  227 |                 "%s%s: %s\n",
      |                 ~~~~~~~~~~~~~
  228 |                 prefix,
      |                 ~~~~~~~
  229 |                 path_type_to_string(s->type),
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  230 |                 s->path);
      |                 ~~~~~~~~

s->type should be valid here, so let's just add an assert.

For https://github.com/systemd/systemd/issues/6119#issuecomment-626073743.
2020-05-09 09:10:25 +02:00
Zbigniew Jędrzejewski-Szmek
f6e9aa9e45 pid1: convert to the new scheme
In all the other cases, I think the code was clearer with the static table.
Here, not so much. And because of the existing dump code, the vtables cannot
be made static and need to remain exported. I still think it's worth to do the
change to have the cmdline introspection, but I'm disappointed with how this
came out.
2020-05-05 22:40:37 +02:00
Michael Chapman
708961c701 core/path: recheck path specs when triggered unit changes state
As documented in systemd.path(5):

    When a service unit triggered by a path unit terminates (regardless
    whether it exited successfully or failed), monitored paths are
    checked immediately again, and the service accordingly restarted
    instantly.

This commit implements this behaviour for PathExists=, PathExistsGlob=,
and DirectoryNotEmpty=. These predicates are essentially
"level-triggered": the service should be activated whenever the
predicate is true. PathChanged= and PathModified=, on the other hand,
are "edge-triggered": the service should only be activated when the
predicate *becomes* true.

The behaviour has been broken since at least as far back as commit
8fca6944c2 ("path: stop watching path specs once we triggered the target
unit"). This commit had systemd stop monitoring inotify whenever the
triggered unit was activated. Unfortunately this meant it never updated
the ->inotify_triggered flag, so it never rechecked the path specs when
the triggered unit deactivated.

With this commit, systemd rechecks all paths specs whenever the
triggered unit deactivates. If any PathExists=, PathExistsGlob= or
DirectoryNotEmpty= predicate passes, the triggered unit is reactivated.

If the target unit is activated by something outside of the path unit,
the path unit immediately transitions to a running state. This ensures
the path unit stops monitoring inotify in this situation.

With this change in place, commit d7cf8c24d4 ("core/path: fix spurious
triggering of PathExists= on restart/reload") is no longer necessary.
The path unit (and its triggered unit) is now always active whenever
the PathExists= predicate passes, so there is no spurious restart when
systemd is reloaded or restarted.
2020-05-05 13:56:02 +10:00
Michael Chapman
f285f07752 core/path: use escaped path in serialization 2020-05-05 13:56:02 +10:00
Lennart Poettering
c80a9a33d0 core: clearly refuse OnFailure= deps on units that can't fail
Similar, refuse triggering deps on units that cannot trigger.

And rework how we ignore After= dependencies on device units, to work
the same way.

See: #14142
2020-01-09 11:03:53 +01:00
Zbigniew Jędrzejewski-Szmek
2d8898f564 Merge pull request #14074 from keszybz/rename-system-options
Rename system-options
2019-11-20 16:13:46 +01:00
Zbigniew Jędrzejewski-Szmek
93e63b2a35 core/path: minor simplification 2019-11-18 20:18:34 +01:00
Zbigniew Jędrzejewski-Szmek
d7cf8c24d4 core/path: fix spurious triggering of PathExists= on restart/reload
Our handling of the condition was inconsistent. Normally, we'd only fire when
the file was created (or removed and subsequently created again). But on restarts,
we'd do a "recheck" from path_coldplug(), and if the file existed, we'd
always trigger. Daemon restarts and reloads should not be observeable, in
the sense that they should not trigger units which were already triggered and
would not be started again under normal circumstances.

Note that the mechanism for checks is racy: we get a notification from inotify,
and by the time we check, the file could have been created and removed again,
or removed and created again. It would be better if we inotify would give as
an unambiguous signal that the file was created, but it doesn't: IN_DELETE_SELF
triggers on inode removal, not directory entry, so we need to include IN_ATTRIB,
which obviously triggers on other conditions.

Fixes #12801.
2019-11-18 14:20:05 +01:00
Zbigniew Jędrzejewski-Szmek
7a16cd4b05 core/path: serialize the previous_exists state
Without that we are prone to generate spurious events after daemon
reload/restart.
2019-11-18 14:13:05 +01:00
Zbigniew Jędrzejewski-Szmek
75193d4128 core: adjust load functions for other unit types to be more like service
No functional change, just adjusting code to follow the same pattern
everywhere. In particular, never call _verify() on an already loaded unit,
but return early from the caller instead. This makes the code a bit easier
to follow.
2019-10-11 13:46:05 +02:00
Zbigniew Jędrzejewski-Szmek
c362077087 core: turn unit_load_fragment_and_dropin_optional() into a flag
unit_load_fragment_and_dropin() and unit_load_fragment_and_dropin_optional()
are really the same, with one minor difference in behaviour. Let's drop
the second function.

"_optional" in the name suggests that it's the "dropin" part that is optional.
(Which it is, but in this case, we mean the fragment to be optional.)
I think the new version with a flag is easier to understand.
2019-10-11 10:45:33 +02:00
Franck Bui
27c3112dcb fs-util: introduce inotify_add_watch_and_warn() helper
The default message for ENOSPC is very misleading: it says that the disk is
filled, but in fact the inotify watch limit is the problem.

So let's introduce and use a wrapper that simply calls inotify_add_watch(2) and
which fixes the error message up in case ENOSPC is returned.
2019-10-05 08:08:20 +02:00
Michal Sekletar
8fca6944c2 path: stop watching path specs once we triggered the target unit
We start watching them again once we get a notification that triggered
unit entered inactive or failed state.

Fixes: #10503
2019-09-17 10:11:32 +02:00
Yu Watanabe
4bbccb02ea tree-wide: introduce strerror_safe() 2019-07-05 02:43:56 +09:00
Lennart Poettering
50cbaba4fe core: add new API for enqueing a job with returning the transaction data 2019-03-27 12:37:37 +01:00
Lennart Poettering
a4191c9fb5 core: unify code for checking whether unit to trigger is loaded 2019-03-18 16:06:36 +01:00
Lennart Poettering
97a3f4ee05 core: rename unit_{start_limit|condition|assert}_test() to unit_test_xyz()
Just some renaming, no change in behaviour.

Background: I'd like to add more functions unit_test_xyz() that test
various things, hence let's streamline the naming a bit.
2019-03-18 16:06:36 +01:00
Lennart Poettering
6fcbec6f9b core: whenever we change state of a unit, force out PropertiesChanged bus signal
This allows clients to follow our internal state changes safely.

Previously, quick state changes (for example, when we restart a unit due
to Restart= after it quickly transitioned through DEAD/FAILED states)
would be coalesced into one bus signal event, with this change there's
the guarantee that all state changes after the unit was announced ones
are reflected on th bus.

Note we only do this kind of guaranteed flushing only for unit state
changes, not for other unit property changes, where clients still have
to expect coalescing. This is because the unit state is a very
important, high-level concept.

Fixes: #10185
2018-12-01 12:53:26 +01:00
Zbigniew Jędrzejewski-Szmek
baaa35ad70 coccinelle: make use of SYNTHETIC_ERRNO
Ideally, coccinelle would strip unnecessary braces too. But I do not see any
option in coccinelle for this, so instead, I edited the patch text using
search&replace to remove the braces. Unfortunately this is not fully automatic,
in particular it didn't deal well with if-else-if-else blocks and ifdefs, so
there is an increased likelikehood be some bugs in such spots.

I also removed part of the patch that coccinelle generated for udev, where we
returns -1 for failure. This should be fixed independently.
2018-11-22 10:54:38 +01:00
Zbigniew Jędrzejewski-Szmek
aac99f303a core: introduce a helper function to wrap unit_log_{success,failure}
It's inline so that the compiler can easily optimize away the call to get
status string.
2018-11-16 19:47:07 +01:00
Lennart Poettering
523ee2d414 core: log a recognizable message when a unit succeeds, too
We already are doing it on failure, let's do it on success, too.

Fixes: #10265
2018-11-16 15:22:48 +01:00
Lennart Poettering
7c047d7443 core: make log messages about units entering a 'failed' state recognizable
Let's make this recognizable, and carry result information in a
structure fashion.
2018-11-16 15:22:48 +01:00
Lennart Poettering
d68c645bd3 core: rework serialization
Let's be more careful with what we serialize: let's ensure we never
serialize strings that are longer than LONG_LINE_MAX, so that we know we
can read them back with read_line(…, LONG_LINE_MAX, …) safely.

In order to implement this all serialization functions are move to
serialize.[ch], and internally will do line size checks. We'd rather
skip a serialization line (with a loud warning) than write an overly
long line out. Of course, this is just a second level protection, after
all the data we serialize shouldn't be this long in the first place.

While we are at it also clean up logging: while serializing make sure to
always log about errors immediately. Also, (void)ify all calls we don't
expect errors in (or catch errors as part of the general
fflush_and_check() at the end.
2018-10-26 10:52:41 +02:00
Zbigniew Jędrzejewski-Szmek
5a72417084 pid1: drop unused path parameter to add_two_dependencies_by_name() 2018-09-15 20:02:00 +02:00
Zbigniew Jędrzejewski-Szmek
35d8c19ace pid1: drop now-unused path parameter to add_dependency_by_name() 2018-09-15 19:57:52 +02:00
Lennart Poettering
0c69794138 tree-wide: remove Lennart's copyright lines
These lines are generally out-of-date, incomplete and unnecessary. With
SPDX and git repository much more accurate and fine grained information
about licensing and authorship is available, hence let's drop the
per-file copyright notice. Of course, removing copyright lines of others
is problematic, hence this commit only removes my own lines and leaves
all others untouched. It might be nicer if sooner or later those could
go away too, making git the only and accurate source of authorship
information.
2018-06-14 10:20:20 +02:00