summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-04-02 14:27:27 +0200
committerGitHub <noreply@github.com>2019-04-02 14:27:27 +0200
commit84ce204a93841776f022712d11219c616e585192 (patch)
treeca2a4af543e2b8e5f431b85fc2842aa3fff61794
parent8a306989b3343e27edd7f59633b2d909781e0474 (diff)
parentefc19ee4856f4dd5c47df466f3cc7f8496dd3c1a (diff)
downloadsystemd-84ce204a93841776f022712d11219c616e585192.tar.gz
Merge pull request #12185 from poettering/login-unstore-fd
logind: remove unused fds from fdstore
-rw-r--r--src/login/logind-session-device.c20
-rw-r--r--src/login/logind.c122
2 files changed, 66 insertions, 76 deletions
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index f358524ebc..7c79a4afdc 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -387,21 +387,11 @@ void session_device_free(SessionDevice *sd) {
assert(sd);
/* Make sure to remove the pushed fd. */
- if (sd->pushed_fd) {
- _cleanup_free_ char *m = NULL;
- const char *id;
- int r;
-
- /* Session ID does not contain separators. */
- id = sd->session->id;
- assert(*(id + strcspn(id, "-\n")) == '\0');
-
- r = asprintf(&m, "FDSTOREREMOVE=1\n"
- "FDNAME=session-%s-device-%u-%u\n",
- id, major(sd->dev), minor(sd->dev));
- if (r >= 0)
- (void) sd_notify(false, m);
- }
+ if (sd->pushed_fd)
+ (void) sd_notifyf(false,
+ "FDSTOREREMOVE=1\n"
+ "FDNAME=session-%s-device-%u-%u",
+ sd->session->id, major(sd->dev), minor(sd->dev));
session_device_stop(sd);
session_device_notify(sd, SESSION_DEVICE_RELEASE);
diff --git a/src/login/logind.c b/src/login/logind.c
index c78994aae6..4c0e8ce6b1 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -378,73 +378,75 @@ static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) {
return 0;
}
-static int manager_attach_fds(Manager *m) {
- _cleanup_strv_free_ char **fdnames = NULL;
- int n, i, fd;
+static int deliver_fd(Manager *m, const char *fdname, int fd) {
+ _cleanup_free_ char *id = NULL;
+ SessionDevice *sd;
+ struct stat st;
+ Session *s;
+ dev_t dev;
+ int r;
- /* Upon restart, PID1 will send us back all fds of session devices
- * that we previously opened. Each file descriptor is associated
- * with a given session. The session ids are passed through FDNAMES. */
+ assert(m);
+ assert(fd >= 0);
- n = sd_listen_fds_with_names(true, &fdnames);
- if (n <= 0)
- return n;
-
- for (i = 0; i < n; i++) {
- _cleanup_free_ char *id = NULL;
- dev_t dev;
- struct stat st;
- SessionDevice *sd;
- Session *s;
- int r;
+ r = parse_fdname(fdname, &id, &dev);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse fd name %s: %m", fdname);
- fd = SD_LISTEN_FDS_START + i;
+ s = hashmap_get(m->sessions, id);
+ if (!s)
+ /* If the session doesn't exist anymore, the associated session device attached to this fd
+ * doesn't either. Let's simply close this fd. */
+ return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Failed to attach fd for unknown session: %s", id);
- r = parse_fdname(fdnames[i], &id, &dev);
- if (r < 0) {
- log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]);
- close_nointr(fd);
- continue;
- }
+ if (fstat(fd, &st) < 0)
+ /* The device is allowed to go away at a random point, in which case fstat() failing is
+ * expected. */
+ return log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id);
- s = hashmap_get(m->sessions, id);
- if (!s) {
- /* If the session doesn't exist anymore, the associated session
- * device attached to this fd doesn't either. Let's simply close
- * this fd. */
- log_debug("Failed to attach fd for unknown session: %s", id);
- close_nointr(fd);
- continue;
- }
+ if (!S_ISCHR(st.st_mode) || st.st_rdev != dev)
+ return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "Device fd doesn't point to the expected character device node");
- if (fstat(fd, &st) < 0) {
- /* The device is allowed to go away at a random point, in which
- * case fstat failing is expected. */
- log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id);
- close_nointr(fd);
- continue;
- }
+ sd = hashmap_get(s->devices, &dev);
+ if (!sd)
+ /* Weird, we got an fd for a session device which wasn't recorded in the session state
+ * file... */
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODEV), "Got fd for missing session device [%u:%u] in session %s",
+ major(dev), minor(dev), s->id);
- if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) {
- log_debug("Device fd doesn't point to the expected character device node");
- close_nointr(fd);
- continue;
- }
+ log_debug("Attaching fd to session device [%u:%u] for session %s",
+ major(dev), minor(dev), s->id);
+
+ session_device_attach_fd(sd, fd, s->was_active);
+ return 0;
+}
+
+static int manager_attach_fds(Manager *m) {
+ _cleanup_strv_free_ char **fdnames = NULL;
+ int n;
+
+ /* Upon restart, PID1 will send us back all fds of session devices that we previously opened. Each
+ * file descriptor is associated with a given session. The session ids are passed through FDNAMES. */
- sd = hashmap_get(s->devices, &dev);
- if (!sd) {
- /* Weird, we got an fd for a session device which wasn't
- * recorded in the session state file... */
- log_warning("Got fd for missing session device [%u:%u] in session %s",
- major(dev), minor(dev), s->id);
- close_nointr(fd);
+ n = sd_listen_fds_with_names(true, &fdnames);
+ if (n < 0)
+ return log_warning_errno(n, "Failed to acquire passed fd list: %m");
+ if (n == 0)
+ return 0;
+
+ for (int i = 0; i < n; i++) {
+ int fd = SD_LISTEN_FDS_START + i;
+
+ if (deliver_fd(m, fdnames[i], fd) >= 0)
continue;
- }
- log_debug("Attaching fd to session device [%u:%u] for session %s",
- major(dev), minor(dev), s->id);
+ /* Hmm, we couldn't deliver the fd to any session device object? If so, let's close the fd */
+ safe_close(fd);
- session_device_attach_fd(sd, fd, s->was_active);
+ /* Remove from fdstore as well */
+ (void) sd_notifyf(false,
+ "FDSTOREREMOVE=1\n"
+ "FDNAME=%s", fdnames[i]);
}
return 0;
@@ -492,11 +494,9 @@ static int manager_enumerate_sessions(Manager *m) {
r = k;
}
- /* We might be restarted and PID1 could have sent us back the
- * session device fds we previously saved. */
- k = manager_attach_fds(m);
- if (k < 0)
- log_warning_errno(k, "Failed to reattach session device fds: %m");
+ /* We might be restarted and PID1 could have sent us back the session device fds we previously
+ * saved. */
+ (void) manager_attach_fds(m);
return r;
}