1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-03 01:17:45 +03:00

Merge pull request #14030 from keszybz/path-no-trigger

Fix spurious triggering of PathExists=
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-11-18 22:20:07 +01:00 committed by GitHub
commit 3049e6a233
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 17 deletions

View File

@ -52,11 +52,7 @@ void path_hash_func(const char *q, struct siphash *state) {
}
}
int path_compare_func(const char *a, const char *b) {
return path_compare(a, b);
}
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare_func);
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare);
void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state);

View File

@ -79,7 +79,6 @@ extern const struct hash_ops string_hash_ops;
extern const struct hash_ops string_hash_ops_free_free;
void path_hash_func(const char *p, struct siphash *state);
int path_compare_func(const char *a, const char *b) _pure_;
extern const struct hash_ops path_hash_ops;
/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings

View File

@ -897,7 +897,7 @@ static const char* counting_what(void) {
return "userspace processes (excl. kernel)";
}
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(group_hash_ops, char, path_hash_func, path_compare_func, Group, group_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(group_hash_ops, char, path_hash_func, path_compare, Group, group_free);
static int run(int argc, char *argv[]) {
_cleanup_hashmap_free_ Hashmap *a = NULL, *b = NULL;

View File

@ -9,12 +9,14 @@
#include "bus-util.h"
#include "dbus-path.h"
#include "dbus-unit.h"
#include "escape.h"
#include "fd-util.h"
#include "fs-util.h"
#include "glob-util.h"
#include "macro.h"
#include "mkdir.h"
#include "path.h"
#include "path-util.h"
#include "serialize.h"
#include "special.h"
#include "stat-util.h"
@ -27,19 +29,18 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
[PATH_DEAD] = UNIT_INACTIVE,
[PATH_WAITING] = UNIT_ACTIVE,
[PATH_RUNNING] = UNIT_ACTIVE,
[PATH_FAILED] = UNIT_FAILED
[PATH_FAILED] = UNIT_FAILED,
};
static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
static const int flags_table[_PATH_TYPE_MAX] = {
[PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
[PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
[PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO,
[PATH_MODIFIED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY,
[PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO
[PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO,
};
bool exists = false;
@ -174,12 +175,14 @@ int path_spec_fd_event(PathSpec *s, uint32_t revents) {
}
static bool path_spec_check_good(PathSpec *s, bool initial) {
bool good = false;
bool b, good = false;
switch (s->type) {
case PATH_EXISTS:
good = access(s->path, F_OK) >= 0;
b = access(s->path, F_OK) >= 0;
good = b && !s->previous_exists;
s->previous_exists = b;
break;
case PATH_EXISTS_GLOB:
@ -195,14 +198,11 @@ static bool path_spec_check_good(PathSpec *s, bool initial) {
}
case PATH_CHANGED:
case PATH_MODIFIED: {
bool b;
case PATH_MODIFIED:
b = access(s->path, F_OK) >= 0;
good = !initial && b != s->previous_exists;
s->previous_exists = b;
break;
}
default:
;
@ -601,6 +601,7 @@ static int path_stop(Unit *u) {
static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
Path *p = PATH(u);
PathSpec *s;
assert(u);
assert(f);
@ -609,6 +610,19 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
(void) serialize_item(f, "state", path_state_to_string(p->state));
(void) serialize_item(f, "result", path_result_to_string(p->result));
LIST_FOREACH(spec, s, p->specs) {
_cleanup_free_ char *escaped = NULL;
escaped = cescape(s->path);
if (!escaped)
return log_oom();
(void) serialize_item_format(f, "path-spec", "%s %i %s",
path_type_to_string(s->type),
s->previous_exists,
s->path);
}
return 0;
}
@ -638,6 +652,38 @@ static int path_deserialize_item(Unit *u, const char *key, const char *value, FD
else if (f != PATH_SUCCESS)
p->result = f;
} else if (streq(key, "path-spec")) {
int previous_exists, skip = 0, r;
_cleanup_free_ char *type_str = NULL;
if (sscanf(value, "%ms %i %n", &type_str, &previous_exists, &skip) < 2)
log_unit_debug(u, "Failed to parse path-spec value: %s", value);
else {
_cleanup_free_ char *unescaped = NULL;
PathType type;
PathSpec *s;
type = path_type_from_string(type_str);
if (type < 0) {
log_unit_warning(u, "Unknown path type \"%s\", ignoring.", type_str);
return 0;
}
r = cunescape(value+skip, 0, &unescaped);
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to unescape serialize path: %m");
return 0;
}
LIST_FOREACH(spec, s, p->specs)
if (s->type == type &&
path_equal(s->path, unescaped)) {
s->previous_exists = previous_exists;
break;
}
}
} else
log_unit_debug(u, "Unknown serialization key: %s", key);
@ -670,7 +716,7 @@ static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
return 0;
/* log_debug("inotify wakeup on %s.", u->id); */
/* log_debug("inotify wakeup on %s.", UNIT(p)->id); */
LIST_FOREACH(spec, s, p->specs)
if (path_spec_owns_inotify_fd(s, fd))