2020-11-09 05:23:58 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
#include <stdbool.h>
|
2018-04-04 11:17:19 +02:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
2014-11-05 21:27:01 +01:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2018-05-15 20:17:34 +02:00
|
|
|
#include "all-units.h"
|
2015-10-26 21:16:26 +01:00
|
|
|
#include "fd-util.h"
|
|
|
|
#include "fs-util.h"
|
2014-11-05 21:27:01 +01:00
|
|
|
#include "macro.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "manager.h"
|
2014-11-05 21:27:01 +01:00
|
|
|
#include "mkdir.h"
|
2018-09-12 08:15:09 +02:00
|
|
|
#include "path-util.h"
|
2015-04-04 11:52:57 +02:00
|
|
|
#include "rm-rf.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
|
|
|
#include "strv.h"
|
2016-04-08 18:54:05 +02:00
|
|
|
#include "tests.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "unit.h"
|
|
|
|
#include "util.h"
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
typedef void (*test_function_t)(Manager *m);
|
|
|
|
|
|
|
|
static int setup_test(Manager **m) {
|
|
|
|
char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit",
|
|
|
|
"directorynotempty", "makedirectory");
|
|
|
|
char **test_path;
|
2015-03-27 12:02:49 +01:00
|
|
|
Manager *tmp = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert_se(m);
|
|
|
|
|
2019-11-08 16:57:25 +01:00
|
|
|
r = enter_cgroup_subroot(NULL);
|
2018-09-13 13:34:12 +02:00
|
|
|
if (r == -ENOMEDIUM)
|
|
|
|
return log_tests_skipped("cgroupfs not available");
|
tests: when running a manager object in a test, migrate to private cgroup subroot first (#6576)
Without this "meson test" will end up running all tests in the same
cgroup root, and they all will try to manage it. Which usually isn't too
bad, except when they end up clearing up each other's cgroups. This race
is hard to trigger but has caused various CI runs to fail spuriously.
With this change we simply move every test that runs a manager object
into their own private cgroup. Note that we don't clean up the cgroup at
the end, we leave that to the cgroup manager around it.
This fixes races that become visible by test runs throwing out errors
like this:
```
exec-systemcallfilter-failing.service: Passing 0 fds to service
exec-systemcallfilter-failing.service: About to execute: /bin/echo 'This should not be seen'
exec-systemcallfilter-failing.service: Forked /bin/echo as 5693
exec-systemcallfilter-failing.service: Changed dead -> start
exec-systemcallfilter-failing.service: Failed to attach to cgroup /exec-systemcallfilter-failing.service: No such file or directory
Received SIGCHLD from PID 5693 ((echo)).
Child 5693 ((echo)) died (code=exited, status=219/CGROUP)
exec-systemcallfilter-failing.service: Child 5693 belongs to exec-systemcallfilter-failing.service
exec-systemcallfilter-failing.service: Main process exited, code=exited, status=219/CGROUP
exec-systemcallfilter-failing.service: Changed start -> failed
exec-systemcallfilter-failing.service: Unit entered failed state.
exec-systemcallfilter-failing.service: Failed with result 'exit-code'.
exec-systemcallfilter-failing.service: cgroup is empty
Assertion 'service->main_exec_status.status == status_expected' failed at ../src/src/test/test-execute.c:71, function check(). Aborting.
```
BTW, I tracked this race down by using perf:
```
# perf record -e cgroup:cgroup_mkdir,cgroup_rmdir
…
# perf script
```
Thanks a lot @iaguis, @alban for helping me how to use perf for this.
Fixes #5895.
2017-08-09 15:42:49 +02:00
|
|
|
|
2018-03-10 11:02:18 +01:00
|
|
|
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &tmp);
|
2019-11-08 16:37:15 +01:00
|
|
|
if (manager_errno_skip_test(r))
|
2018-09-13 16:11:16 +02:00
|
|
|
return log_tests_skipped_errno(r, "manager_new");
|
2014-11-05 21:27:01 +01:00
|
|
|
assert_se(r >= 0);
|
|
|
|
assert_se(manager_startup(tmp, NULL, NULL) >= 0);
|
|
|
|
|
|
|
|
STRV_FOREACH(test_path, tests_path) {
|
2015-04-04 11:52:57 +02:00
|
|
|
_cleanup_free_ char *p = NULL;
|
|
|
|
|
2016-10-23 17:43:27 +02:00
|
|
|
p = strjoin("/tmp/test-path_", *test_path);
|
2015-04-04 11:52:57 +02:00
|
|
|
assert_se(p);
|
|
|
|
|
|
|
|
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
*m = tmp;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void shutdown_test(Manager *m) {
|
|
|
|
assert_se(m);
|
|
|
|
|
|
|
|
manager_free(m);
|
|
|
|
}
|
|
|
|
|
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 05:50:04 +02:00
|
|
|
static Service *service_for_path(Manager *m, Path *path, const char *service_name) {
|
2014-11-05 21:27:01 +01:00
|
|
|
_cleanup_free_ char *tmp = NULL;
|
|
|
|
Unit *service_unit = NULL;
|
|
|
|
|
|
|
|
assert_se(m);
|
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 05:50:04 +02:00
|
|
|
assert_se(path);
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
if (!service_name) {
|
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 05:50:04 +02:00
|
|
|
assert_se(tmp = strreplace(UNIT(path)->id, ".path", ".service"));
|
2014-11-05 21:27:01 +01:00
|
|
|
service_unit = manager_get_unit(m, tmp);
|
|
|
|
} else
|
|
|
|
service_unit = manager_get_unit(m, service_name);
|
|
|
|
assert_se(service_unit);
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
return SERVICE(service_unit);
|
|
|
|
}
|
|
|
|
|
2020-07-31 10:36:57 +02:00
|
|
|
static int _check_states(unsigned line,
|
|
|
|
Manager *m, Path *path, Service *service, PathState path_state, ServiceState service_state) {
|
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 05:50:04 +02:00
|
|
|
assert_se(m);
|
|
|
|
assert_se(service);
|
2014-11-05 21:27:01 +01:00
|
|
|
|
test-path: increase timeout
The tests fail in Fedora's koji with a timeout. Let's just bump
the timeout:
--- stderr ---
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-exists.service: Failed to create cgroup /system.slice/kojid.service/path-exists.service: Permission denied
path-exists.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-exists.service: Failed to create cgroup /system.slice/kojid.service/path-exists.service: Permission denied
path-exists.service: Succeeded.
path-exists.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-existsglob.service: Failed to create cgroup /system.slice/kojid.service/path-existsglob.service: Permission denied
path-existsglob.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-existsglob.service: Failed to create cgroup /system.slice/kojid.service/path-existsglob.service: Permission denied
path-existsglob.service: Succeeded.
path-existsglob.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-changed.service: Failed to create cgroup /system.slice/kojid.service/path-changed.service: Permission denied
path-changed.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-changed.service: Failed to create cgroup /system.slice/kojid.service/path-changed.service: Permission denied
path-changed.service: Succeeded.
path-changed.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-modified.service: Failed to create cgroup /system.slice/kojid.service/path-modified.service: Permission denied
path-modified.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-modified.service: Failed to create cgroup /system.slice/kojid.service/path-modified.service: Permission denied
path-modified.service: Succeeded.
path-modified.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-mycustomunit.service: Failed to create cgroup /system.slice/kojid.service/path-mycustomunit.service: Permission denied
path-mycustomunit.service: Succeeded.
path-unit.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-directorynotempty.service: Failed to create cgroup /system.slice/kojid.service/path-directorynotempty.service: Permission denied
path-directorynotempty.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-directorynotempty.service: Failed to create cgroup /system.slice/kojid.service/path-directorynotempty.service: Permission denied
path-directorynotempty.service: Failed to attach to cgroup /system.slice/kojid.service/path-directorynotempty.service: No such file or directory
path-directorynotempty.service: Failed at step CGROUP spawning /bin/true: No such file or directory
path-directorynotempty.service: Main process exited, code=exited, status=219/CGROUP
path-directorynotempty.service: Failed with result 'exit-code'.
Test timeout when testing path-directorynotempty.path
2020-07-27 15:08:35 +02:00
|
|
|
usec_t end = now(CLOCK_MONOTONIC) + 30 * USEC_PER_SEC;
|
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 05:50:04 +02:00
|
|
|
|
2020-09-14 08:56:28 +02:00
|
|
|
while (path->state != path_state || service->state != service_state ||
|
|
|
|
path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS) {
|
2014-11-05 21:27:01 +01:00
|
|
|
|
test-path: increase timeout
The tests fail in Fedora's koji with a timeout. Let's just bump
the timeout:
--- stderr ---
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-exists.service: Failed to create cgroup /system.slice/kojid.service/path-exists.service: Permission denied
path-exists.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-exists.service: Failed to create cgroup /system.slice/kojid.service/path-exists.service: Permission denied
path-exists.service: Succeeded.
path-exists.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-existsglob.service: Failed to create cgroup /system.slice/kojid.service/path-existsglob.service: Permission denied
path-existsglob.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-existsglob.service: Failed to create cgroup /system.slice/kojid.service/path-existsglob.service: Permission denied
path-existsglob.service: Succeeded.
path-existsglob.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-changed.service: Failed to create cgroup /system.slice/kojid.service/path-changed.service: Permission denied
path-changed.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-changed.service: Failed to create cgroup /system.slice/kojid.service/path-changed.service: Permission denied
path-changed.service: Succeeded.
path-changed.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-modified.service: Failed to create cgroup /system.slice/kojid.service/path-modified.service: Permission denied
path-modified.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-modified.service: Failed to create cgroup /system.slice/kojid.service/path-modified.service: Permission denied
path-modified.service: Succeeded.
path-modified.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-mycustomunit.service: Failed to create cgroup /system.slice/kojid.service/path-mycustomunit.service: Permission denied
path-mycustomunit.service: Succeeded.
path-unit.path: Succeeded.
Failed to connect to system bus: No such file or directory
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-directorynotempty.service: Failed to create cgroup /system.slice/kojid.service/path-directorynotempty.service: Permission denied
path-directorynotempty.service: Succeeded.
-.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied
path-directorynotempty.service: Failed to create cgroup /system.slice/kojid.service/path-directorynotempty.service: Permission denied
path-directorynotempty.service: Failed to attach to cgroup /system.slice/kojid.service/path-directorynotempty.service: No such file or directory
path-directorynotempty.service: Failed at step CGROUP spawning /bin/true: No such file or directory
path-directorynotempty.service: Main process exited, code=exited, status=219/CGROUP
path-directorynotempty.service: Failed with result 'exit-code'.
Test timeout when testing path-directorynotempty.path
2020-07-27 15:08:35 +02:00
|
|
|
assert_se(sd_event_run(m->event, 100 * USEC_PER_MSEC) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
|
2020-09-14 08:56:28 +02:00
|
|
|
usec_t n = now(CLOCK_MONOTONIC);
|
|
|
|
log_info("line %u: %s: state = %s; result = %s (left: %" PRIi64 ")",
|
|
|
|
line,
|
|
|
|
UNIT(path)->id,
|
|
|
|
path_state_to_string(path->state),
|
|
|
|
path_result_to_string(path->result),
|
|
|
|
end - n);
|
|
|
|
log_info("line %u: %s: state = %s; result = %s",
|
|
|
|
line,
|
|
|
|
UNIT(service)->id,
|
|
|
|
service_state_to_string(service->state),
|
|
|
|
service_result_to_string(service->result));
|
|
|
|
|
2020-07-31 10:36:57 +02:00
|
|
|
if (service->state == SERVICE_FAILED &&
|
2020-10-21 10:07:23 +02:00
|
|
|
service->main_exec_status.status == EXIT_CGROUP &&
|
|
|
|
!ci_environment())
|
2020-07-31 10:36:57 +02:00
|
|
|
/* On a general purpose system we may fail to start the service for reasons which are
|
|
|
|
* not under our control: permission limits, resource exhaustion, etc. Let's skip the
|
2020-10-21 10:07:23 +02:00
|
|
|
* test in those cases. On developer machines we require proper setup. */
|
2020-07-31 10:36:57 +02:00
|
|
|
return log_notice_errno(SYNTHETIC_ERRNO(ECANCELED),
|
|
|
|
"Failed to start service %s, aborting test: %s/%s",
|
|
|
|
UNIT(service)->id,
|
|
|
|
service_state_to_string(service->state),
|
|
|
|
service_result_to_string(service->result));
|
|
|
|
|
2020-09-14 08:56:28 +02:00
|
|
|
if (n >= end) {
|
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 05:50:04 +02:00
|
|
|
log_error("Test timeout when testing %s", UNIT(path)->id);
|
2014-11-05 21:27:01 +01:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
2020-07-31 10:36:57 +02:00
|
|
|
|
|
|
|
return 0;
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
2020-09-14 08:56:28 +02:00
|
|
|
#define check_states(...) _check_states(__LINE__, __VA_ARGS__)
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
static void test_path_exists(Manager *m) {
|
|
|
|
const char *test_path = "/tmp/test-path_exists";
|
|
|
|
Unit *unit = NULL;
|
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 05:50:04 +02:00
|
|
|
Path *path = NULL;
|
|
|
|
Service *service = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(m);
|
|
|
|
|
2018-04-12 15:51:39 +02:00
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit) >= 0);
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
path = PATH(unit);
|
|
|
|
service = service_for_path(m, path, NULL);
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_start(unit) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(touch(test_path) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
/* Service restarts if file still exists */
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
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 05:50:04 +02:00
|
|
|
assert_se(unit_stop(unit) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_path_existsglob(Manager *m) {
|
|
|
|
const char *test_path = "/tmp/test-path_existsglobFOOBAR";
|
|
|
|
Unit *unit = NULL;
|
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 05:50:04 +02:00
|
|
|
Path *path = NULL;
|
|
|
|
Service *service = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(m);
|
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 05:50:04 +02:00
|
|
|
|
2018-04-12 15:51:39 +02:00
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit) >= 0);
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
path = PATH(unit);
|
|
|
|
service = service_for_path(m, path, NULL);
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_start(unit) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(touch(test_path) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
/* Service restarts if file still exists */
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
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 05:50:04 +02:00
|
|
|
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(unit_stop(unit) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_path_changed(Manager *m) {
|
|
|
|
const char *test_path = "/tmp/test-path_changed";
|
|
|
|
FILE *f;
|
|
|
|
Unit *unit = NULL;
|
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 05:50:04 +02:00
|
|
|
Path *path = NULL;
|
|
|
|
Service *service = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(m);
|
|
|
|
|
2018-04-12 15:51:39 +02:00
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit) >= 0);
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
path = PATH(unit);
|
|
|
|
service = service_for_path(m, path, NULL);
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_start(unit) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(touch(test_path) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
/* Service does not restart if file still exists */
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
f = fopen(test_path, "w");
|
|
|
|
assert_se(f);
|
|
|
|
fclose(f);
|
|
|
|
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
|
|
|
|
assert_se(unit_stop(unit) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_path_modified(Manager *m) {
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
const char *test_path = "/tmp/test-path_modified";
|
|
|
|
Unit *unit = NULL;
|
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 05:50:04 +02:00
|
|
|
Path *path = NULL;
|
|
|
|
Service *service = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(m);
|
|
|
|
|
2018-04-12 15:51:39 +02:00
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit) >= 0);
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
path = PATH(unit);
|
|
|
|
service = service_for_path(m, path, NULL);
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_start(unit) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(touch(test_path) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
/* Service does not restart if file still exists */
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
f = fopen(test_path, "w");
|
|
|
|
assert_se(f);
|
|
|
|
fputs("test", f);
|
|
|
|
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
|
|
|
|
assert_se(unit_stop(unit) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_path_unit(Manager *m) {
|
|
|
|
const char *test_path = "/tmp/test-path_unit";
|
|
|
|
Unit *unit = NULL;
|
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 05:50:04 +02:00
|
|
|
Path *path = NULL;
|
|
|
|
Service *service = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(m);
|
|
|
|
|
2018-04-12 15:51:39 +02:00
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit) >= 0);
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
path = PATH(unit);
|
|
|
|
service = service_for_path(m, path, "path-mycustomunit.service");
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_start(unit) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(touch(test_path) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
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 05:50:04 +02:00
|
|
|
assert_se(unit_stop(unit) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_path_directorynotempty(Manager *m) {
|
|
|
|
const char *test_path = "/tmp/test-path_directorynotempty/";
|
|
|
|
Unit *unit = NULL;
|
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 05:50:04 +02:00
|
|
|
Path *path = NULL;
|
|
|
|
Service *service = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
assert_se(m);
|
|
|
|
|
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 05:50:04 +02:00
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit) >= 0);
|
|
|
|
|
|
|
|
path = PATH(unit);
|
|
|
|
service = service_for_path(m, path, NULL);
|
|
|
|
|
2014-11-05 21:27:01 +01:00
|
|
|
assert_se(access(test_path, F_OK) < 0);
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_start(unit) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
/* MakeDirectory default to no */
|
|
|
|
assert_se(access(test_path, F_OK) < 0);
|
|
|
|
|
|
|
|
assert_se(mkdir_p(test_path, 0755) >= 0);
|
2015-02-03 02:05:59 +01:00
|
|
|
assert_se(touch(strjoina(test_path, "test_file")) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
/* Service restarts if directory is still not empty */
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_RUNNING, SERVICE_RUNNING) < 0)
|
|
|
|
return;
|
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 05:50:04 +02:00
|
|
|
|
|
|
|
assert_se(rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
|
|
|
|
assert_se(unit_stop(UNIT(service)) >= 0);
|
2020-07-31 10:36:57 +02:00
|
|
|
if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
|
|
|
|
return;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
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 05:50:04 +02:00
|
|
|
assert_se(unit_stop(unit) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_path_makedirectory_directorymode(Manager *m) {
|
|
|
|
const char *test_path = "/tmp/test-path_makedirectory/";
|
|
|
|
Unit *unit = NULL;
|
|
|
|
struct stat s;
|
|
|
|
|
|
|
|
assert_se(m);
|
|
|
|
|
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 05:50:04 +02:00
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit) >= 0);
|
|
|
|
|
2014-11-05 21:27:01 +01:00
|
|
|
assert_se(access(test_path, F_OK) < 0);
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_start(unit) >= 0);
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
/* Check if the directory has been created */
|
|
|
|
assert_se(access(test_path, F_OK) >= 0);
|
|
|
|
|
|
|
|
/* Check the mode we specified with DirectoryMode=0744 */
|
|
|
|
assert_se(stat(test_path, &s) >= 0);
|
|
|
|
assert_se((s.st_mode & S_IRWXU) == 0700);
|
|
|
|
assert_se((s.st_mode & S_IRWXG) == 0040);
|
|
|
|
assert_se((s.st_mode & S_IRWXO) == 0004);
|
|
|
|
|
2018-11-19 14:48:28 +01:00
|
|
|
assert_se(unit_stop(unit) >= 0);
|
2015-04-04 11:52:57 +02:00
|
|
|
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
|
2014-11-05 21:27:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
2016-04-08 18:54:05 +02:00
|
|
|
static const test_function_t tests[] = {
|
2014-11-05 21:27:01 +01:00
|
|
|
test_path_exists,
|
|
|
|
test_path_existsglob,
|
|
|
|
test_path_changed,
|
|
|
|
test_path_modified,
|
|
|
|
test_path_unit,
|
|
|
|
test_path_directorynotempty,
|
|
|
|
test_path_makedirectory_directorymode,
|
|
|
|
NULL,
|
|
|
|
};
|
2016-04-08 18:54:05 +02:00
|
|
|
|
2018-09-12 08:15:09 +02:00
|
|
|
_cleanup_free_ char *test_path = NULL;
|
2020-07-22 12:12:54 +02:00
|
|
|
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
2018-04-04 11:17:19 +02:00
|
|
|
umask(022);
|
|
|
|
|
2018-09-13 14:31:13 +02:00
|
|
|
test_setup_logging(LOG_INFO);
|
2014-11-05 21:27:01 +01:00
|
|
|
|
2019-12-06 21:51:59 +01:00
|
|
|
assert_se(get_testdata_dir("test-path", &test_path) >= 0);
|
2018-09-12 08:15:09 +02:00
|
|
|
assert_se(set_unit_path(test_path) >= 0);
|
2017-02-14 22:33:52 +01:00
|
|
|
assert_se(runtime_dir = setup_fake_runtime_dir());
|
2014-11-05 21:27:01 +01:00
|
|
|
|
2020-08-27 09:58:58 +02:00
|
|
|
for (const test_function_t *test = tests; *test; test++) {
|
2020-07-22 12:12:54 +02:00
|
|
|
Manager *m = NULL;
|
2014-11-05 21:27:01 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
/* We create a clean environment for each test */
|
|
|
|
r = setup_test(&m);
|
2018-09-13 13:34:12 +02:00
|
|
|
if (r != 0)
|
|
|
|
return r;
|
2014-11-05 21:27:01 +01:00
|
|
|
|
|
|
|
(*test)(m);
|
|
|
|
|
|
|
|
shutdown_test(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|