summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/path.c78
-rw-r--r--src/core/service.c16
2 files changed, 62 insertions, 32 deletions
diff --git a/src/core/path.c b/src/core/path.c
index fc101280a1..01a2b0810e 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -53,8 +53,8 @@ int path_spec_watch(PathSpec *s, Unit *u) {
};
bool exists = false;
- char _cleanup_free_ *k = NULL;
- char *slash;
+ char _cleanup_free_ *path = NULL;
+ char *slash, *oldslash = NULL;
int r;
assert(u);
@@ -62,8 +62,8 @@ int path_spec_watch(PathSpec *s, Unit *u) {
path_spec_unwatch(s, u);
- k = strdup(s->path);
- if (!k)
+ path = strdup(s->path);
+ if (!path)
return -ENOMEM;
s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
@@ -76,43 +76,61 @@ int path_spec_watch(PathSpec *s, Unit *u) {
if (r < 0)
goto fail;
- s->primary_wd = inotify_add_watch(s->inotify_fd, k, flags_table[s->type]);
- if (s->primary_wd >= 0)
- exists = true;
- else if (errno != EACCES && errno != ENOENT) {
- log_error("Failed to add watch on %s: %m", k);
- r = -errno;
- goto fail;
- }
+ /* This assumes the path was passed through path_kill_slashes()! */
- do {
+ for(slash = strchr(path, '/'); ; slash = strchr(slash+1, '/')) {
int flags;
+ char tmp;
+
+ if (slash) {
+ tmp = slash[slash == path];
+ slash[slash == path] = '\0';
+ flags = IN_MOVE_SELF | IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO;
+ } else {
+ flags = flags_table[s->type];
+ }
- /* This assumes the path was passed through path_kill_slashes()! */
- slash = strrchr(k, '/');
- if (!slash)
- break;
-
- /* Trim the path at the last slash. Keep the slash if it's the root dir. */
- slash[slash == k] = 0;
-
- flags = IN_MOVE_SELF;
- if (!exists)
- flags |= IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO;
+ r = inotify_add_watch(s->inotify_fd, path, flags);
+ if (r < 0) {
+ if (errno == EACCES || errno == ENOENT)
+ break;
- if (inotify_add_watch(s->inotify_fd, k, flags) >= 0)
- exists = true;
- else if (errno != EACCES && errno != ENOENT) {
- log_error("Failed to add watch on %s: %m", k);
+ log_warning("Failed to add watch on %s: %m", path);
r = -errno;
goto fail;
+ } else {
+ exists = true;
+
+ /* Path exists, we don't need to watch parent
+ too closely. */
+ if (oldslash) {
+ char tmp2 = oldslash[oldslash == path];
+ oldslash[oldslash == path] = '\0';
+
+ inotify_add_watch(s->inotify_fd, path, IN_MOVE_SELF);
+ /* Error is ignored, the worst can happen is
+ we get spurious events. */
+
+ oldslash[oldslash == path] = tmp2;
+ }
}
- } while (slash != k);
+
+ if (slash) {
+ slash[slash == path] = tmp;
+ oldslash = slash;
+ } else {
+ /* whole path has been iterated over */
+ s->primary_wd = r;
+ break;
+ }
+ }
+
+ assert(errno == EACCES || errno == ENOENT || streq(path, s->path));
if (!exists) {
log_error("Failed to add watch on any of the components of %s: %m",
s->path);
- r = -errno;
+ r = -errno; /* either EACCESS or ENOENT */
goto fail;
}
diff --git a/src/core/service.c b/src/core/service.c
index 3f8aabcf45..61b150cba8 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1400,8 +1400,13 @@ static int service_load_pid_file(Service *s, bool may_warn) {
}
r = parse_pid(k, &pid);
- if (r < 0)
+ if (r < 0) {
+ if (may_warn)
+ log_info_unit(UNIT(s)->id,
+ "Failed to read PID from file %s: %s",
+ s->pid_file, strerror(-r));
return r;
+ }
if (kill(pid, 0) < 0 && errno != EPERM) {
if (may_warn)
@@ -1429,9 +1434,13 @@ static int service_load_pid_file(Service *s, bool may_warn) {
return r;
r = unit_watch_pid(UNIT(s), pid);
- if (r < 0)
+ if (r < 0) {
/* FIXME: we need to do something here */
+ log_warning_unit(UNIT(s)->id,
+ "Failed to watch PID %lu from service %s",
+ (unsigned long) pid, UNIT(s)->id);
return r;
+ }
return 0;
}
@@ -2824,6 +2833,9 @@ static int service_watch_pid_file(Service *s) {
goto fail;
/* the pidfile might have appeared just before we set the watch */
+ log_debug_unit(UNIT(s)->id,
+ "Trying to read %s's PID file %s in case it changed",
+ UNIT(s)->id, s->pid_file_pathspec->path);
service_retry_pid_file(s);
return 0;