Merge pull request #15697 from OhNoMoreGit/fix-path-units

Recheck PathExists=, PathExistsGlob=, DirectoryNotEmpty= when triggered unit terminates
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-06-25 18:23:47 +02:00
committed by GitHub
10 changed files with 183 additions and 77 deletions
+36 -39
View File
@@ -174,15 +174,13 @@ int path_spec_fd_event(PathSpec *s, uint32_t revents) {
return r;
}
static bool path_spec_check_good(PathSpec *s, bool initial) {
static bool path_spec_check_good(PathSpec *s, bool initial, bool from_trigger_notify) {
bool b, good = false;
switch (s->type) {
case PATH_EXISTS:
b = access(s->path, F_OK) >= 0;
good = b && !s->previous_exists;
s->previous_exists = b;
good = access(s->path, F_OK) >= 0;
break;
case PATH_EXISTS_GLOB:
@@ -200,7 +198,7 @@ static bool path_spec_check_good(PathSpec *s, bool initial) {
case PATH_CHANGED:
case PATH_MODIFIED:
b = access(s->path, F_OK) >= 0;
good = !initial && b != s->previous_exists;
good = !initial && !from_trigger_notify && b != s->previous_exists;
s->previous_exists = b;
break;
@@ -425,8 +423,7 @@ static void path_set_state(Path *p, PathState state) {
old_state = p->state;
p->state = state;
if (state != PATH_WAITING &&
(state != PATH_RUNNING || p->inotify_triggered))
if (!IN_SET(state, PATH_WAITING, PATH_RUNNING))
path_unwatch(p);
if (state != old_state)
@@ -435,7 +432,7 @@ static void path_set_state(Path *p, PathState state) {
unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], 0);
}
static void path_enter_waiting(Path *p, bool initial, bool recheck);
static void path_enter_waiting(Path *p, bool initial, bool from_trigger_notify);
static int path_coldplug(Unit *u) {
Path *p = PATH(u);
@@ -446,7 +443,7 @@ static int path_coldplug(Unit *u) {
if (p->deserialized_state != p->state) {
if (IN_SET(p->deserialized_state, PATH_WAITING, PATH_RUNNING))
path_enter_waiting(p, true, true);
path_enter_waiting(p, true, false);
else
path_set_state(p, p->deserialized_state);
}
@@ -486,8 +483,6 @@ static void path_enter_running(Path *p) {
if (r < 0)
goto fail;
p->inotify_triggered = false;
path_set_state(p, PATH_RUNNING);
path_unwatch(p);
@@ -498,27 +493,35 @@ fail:
path_enter_dead(p, PATH_FAILURE_RESOURCES);
}
static bool path_check_good(Path *p, bool initial) {
static bool path_check_good(Path *p, bool initial, bool from_trigger_notify) {
PathSpec *s;
assert(p);
LIST_FOREACH(spec, s, p->specs)
if (path_spec_check_good(s, initial))
if (path_spec_check_good(s, initial, from_trigger_notify))
return true;
return false;
}
static void path_enter_waiting(Path *p, bool initial, bool recheck) {
static void path_enter_waiting(Path *p, bool initial, bool from_trigger_notify) {
Unit *trigger;
int r;
if (recheck)
if (path_check_good(p, initial)) {
log_unit_debug(UNIT(p), "Got triggered.");
path_enter_running(p);
return;
}
/* If the triggered unit is already running, so are we */
trigger = UNIT_TRIGGER(UNIT(p));
if (trigger && !UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(trigger))) {
path_set_state(p, PATH_RUNNING);
path_unwatch(p);
return;
}
if (path_check_good(p, initial, from_trigger_notify)) {
log_unit_debug(UNIT(p), "Got triggered.");
path_enter_running(p);
return;
}
r = path_watch(p);
if (r < 0)
@@ -528,12 +531,11 @@ static void path_enter_waiting(Path *p, bool initial, bool recheck) {
* might have appeared/been removed by now, so we must
* recheck */
if (recheck)
if (path_check_good(p, false)) {
log_unit_debug(UNIT(p), "Got triggered.");
path_enter_running(p);
return;
}
if (path_check_good(p, false, from_trigger_notify)) {
log_unit_debug(UNIT(p), "Got triggered.");
path_enter_running(p);
return;
}
path_set_state(p, PATH_WAITING);
return;
@@ -579,7 +581,7 @@ static int path_start(Unit *u) {
path_mkdir(p);
p->result = PATH_SUCCESS;
path_enter_waiting(p, true, true);
path_enter_waiting(p, true, false);
return 1;
}
@@ -617,7 +619,7 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
(void) serialize_item_format(f, "path-spec", "%s %i %s",
type,
s->previous_exists,
s->path);
escaped);
}
return 0;
@@ -728,15 +730,10 @@ static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
if (changed < 0)
goto fail;
/* If we are already running, then remember that one event was
* dispatched so that we restart the service only if something
* actually changed on disk */
p->inotify_triggered = true;
if (changed)
path_enter_running(p);
else
path_enter_waiting(p, false, true);
path_enter_waiting(p, false, false);
return 0;
@@ -760,11 +757,11 @@ static void path_trigger_notify(Unit *u, Unit *other) {
if (p->state == PATH_RUNNING &&
UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
log_unit_debug(UNIT(p), "Got notified about unit deactivation.");
/* Hmm, so inotify was triggered since the
* last activation, so I guess we need to
* recheck what is going on. */
path_enter_waiting(p, false, p->inotify_triggered);
path_enter_waiting(p, false, true);
} else if (p->state == PATH_WAITING &&
!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
log_unit_debug(UNIT(p), "Got notified about unit activation.");
path_enter_waiting(p, false, true);
}
}
-2
View File
@@ -56,8 +56,6 @@ struct Path {
PathState state, deserialized_state;
bool inotify_triggered;
bool make_directory;
mode_t directory_mode;