[systemd-commits] 5 commits - src/libsystemd-terminal src/shared

David Herrmann dvdhrm at kemper.freedesktop.org
Mon Sep 22 09:21:13 PDT 2014


 src/libsystemd-terminal/evcat.c            |    3 
 src/libsystemd-terminal/grdev-internal.h   |    1 
 src/libsystemd-terminal/grdev.c            |   18 ++
 src/libsystemd-terminal/grdev.h            |    5 
 src/libsystemd-terminal/idev-evdev.c       |  170 +++++-----------------
 src/libsystemd-terminal/idev-internal.h    |    4 
 src/libsystemd-terminal/idev.c             |  114 +++++++++++++++
 src/libsystemd-terminal/modeset.c          |    3 
 src/libsystemd-terminal/sysview-internal.h |    1 
 src/libsystemd-terminal/sysview.c          |  215 +++++++++++++----------------
 src/libsystemd-terminal/sysview.h          |    4 
 src/shared/util.h                          |    2 
 12 files changed, 294 insertions(+), 246 deletions(-)

New commits:
commit 8507eb20b64010b26f23822cbf442bb0bf96511c
Author: Emil Renner Berthing <systemd at esmil.dk>
Date:   Fri Sep 19 20:26:53 2014 +0200

    util: avoid non-portable __WORDSIZE
    
    Lets not unnecessarily rely on __WORDSIZE, which is not clearly specified
    by any spec. Use explicit size comparisons if we're not interested in the
    WORDSIZE, anyway.
    
    (David: adjust commit message to explain why we do this)

diff --git a/src/shared/util.h b/src/shared/util.h
index a1d5657..21a90a4 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -205,7 +205,7 @@ int safe_atod(const char *s, double *ret_d);
 
 int safe_atou8(const char *s, uint8_t *ret);
 
-#if __WORDSIZE == 32
+#if LONG_MAX == INT_MAX
 static inline int safe_atolu(const char *s, unsigned long *ret_u) {
         assert_cc(sizeof(unsigned long) == sizeof(unsigned));
         return safe_atou(s, (unsigned*) ret_u);

commit c17091b79773e9c458f03a897b26c2257d7366a7
Author: David Herrmann <dh.herrmann at gmail.com>
Date:   Mon Sep 22 18:05:19 2014 +0200

    terminal: signal object removal during sysview_context_stop()
    
    Now that we no longer propagate callback return values, we can safely call
    into user-callbacks during sysview_context_stop(). This way, users can
    rely on all objects to be removed via callbacks (except if they failed
    during object creation). This avoids duplicating any object hashtables on
    the users' side and reduces memory consumption.

diff --git a/src/libsystemd-terminal/evcat.c b/src/libsystemd-terminal/evcat.c
index b3f08e6..62556f6 100644
--- a/src/libsystemd-terminal/evcat.c
+++ b/src/libsystemd-terminal/evcat.c
@@ -330,7 +330,8 @@ static int evcat_sysview_fn(sysview_context *c, void *userdata, sysview_event *e
         case SYSVIEW_EVENT_SESSION_REMOVE:
                 idev_session_disable(e->idev_session);
                 e->idev_session = idev_session_free(e->idev_session);
-                sd_event_exit(e->event, 0);
+                if (sd_event_get_exit_code(e->event, &r) == -ENODATA)
+                        sd_event_exit(e->event, 0);
                 break;
         case SYSVIEW_EVENT_SESSION_ATTACH:
                 d = ev->session_attach.device;
diff --git a/src/libsystemd-terminal/modeset.c b/src/libsystemd-terminal/modeset.c
index 7a28e7a..f564fa0 100644
--- a/src/libsystemd-terminal/modeset.c
+++ b/src/libsystemd-terminal/modeset.c
@@ -332,7 +332,8 @@ static int modeset_sysview_fn(sysview_context *c, void *userdata, sysview_event
                 grdev_session_restore(m->grdev_session);
                 grdev_session_disable(m->grdev_session);
                 m->grdev_session = grdev_session_free(m->grdev_session);
-                sd_event_exit(m->event, 0);
+                if (sd_event_get_exit_code(m->event, &r) == -ENODATA)
+                        sd_event_exit(m->event, 0);
                 break;
         case SYSVIEW_EVENT_SESSION_ATTACH:
                 d = ev->session_attach.device;
diff --git a/src/libsystemd-terminal/sysview.c b/src/libsystemd-terminal/sysview.c
index 969514a..cd776f6 100644
--- a/src/libsystemd-terminal/sysview.c
+++ b/src/libsystemd-terminal/sysview.c
@@ -1437,20 +1437,6 @@ void sysview_context_stop(sysview_context *c) {
 
         log_debug("sysview: stop");
 
-        c->running = false;
-        c->scanned = false;
-        c->event_fn = NULL;
-        c->userdata = NULL;
-        c->scan_src = sd_event_source_unref(c->scan_src);
-        context_ud_stop(c);
-        context_ld_stop(c);
-
-        /*
-         * Event-callbacks are already cleared, hence we can safely ignore
-         * return codes of the context_remove_*() helpers. They cannot be
-         * originated from user-callbacks, so we already handled them.
-         */
-
         while ((device = hashmap_first(c->device_map)))
                 context_remove_device(c, device);
 
@@ -1459,6 +1445,14 @@ void sysview_context_stop(sysview_context *c) {
 
         while ((seat = hashmap_first(c->seat_map)))
                 context_remove_seat(c, seat);
+
+        c->running = false;
+        c->scanned = false;
+        c->event_fn = NULL;
+        c->userdata = NULL;
+        c->scan_src = sd_event_source_unref(c->scan_src);
+        context_ud_stop(c);
+        context_ld_stop(c);
 }
 
 static int context_scan_fn(sd_event_source *s, void *userdata) {

commit ed3a9f6a30958ef90a24bc60aec86493974101d3
Author: David Herrmann <dh.herrmann at gmail.com>
Date:   Mon Sep 22 17:55:31 2014 +0200

    terminal: handle callback errors in sysview instead of propagating them
    
    We cannot sanely propagate error codes if we call into user-callbacks
    multiple times for multiple objects. There is no way to merge those errors
    or somehow propagate them.
    
    However, we can just act similar to sd-event and print a log-message while
    discarding the values. This way, we allow error-returns, but can properly
    continue working on our objects.

diff --git a/src/libsystemd-terminal/sysview.c b/src/libsystemd-terminal/sysview.c
index 208c6ce..969514a 100644
--- a/src/libsystemd-terminal/sysview.c
+++ b/src/libsystemd-terminal/sysview.c
@@ -272,7 +272,7 @@ static int session_take_control_fn(sd_bus *bus,
                                    void *userdata,
                                    sd_bus_error *ret_error) {
         sysview_session *session = userdata;
-        int error;
+        int r, error;
 
         session->slot_take_control = sd_bus_slot_unref(session->slot_take_control);
 
@@ -287,7 +287,12 @@ static int session_take_control_fn(sd_bus *bus,
                 error = 0;
         }
 
-        return context_raise_session_control(session->seat->context, session, error);
+        r = context_raise_session_control(session->seat->context, session, error);
+        if (r < 0)
+                log_debug("sysview: callback failed while signalling session control '%d' on session '%s': %s",
+                          error, session->name, strerror(-r));
+
+        return 0;
 }
 
 int sysview_session_take_control(sysview_session *session) {
@@ -548,10 +553,10 @@ static int context_raise_session_refresh(sysview_context *c, sysview_session *se
         return context_raise(c, &event, 0);
 }
 
-static int context_add_device(sysview_context *c, sysview_device *device) {
+static void context_add_device(sysview_context *c, sysview_device *device) {
         sysview_session *session;
-        int r, error = 0;
         Iterator i;
+        int r;
 
         assert(c);
         assert(device);
@@ -564,20 +569,16 @@ static int context_add_device(sysview_context *c, sysview_device *device) {
                         continue;
 
                 r = context_raise_session_attach(c, session, device);
-                if (r != 0)
-                        error = r;
+                if (r < 0)
+                        log_debug("sysview: callback failed while attaching device '%s' to session '%s': %s",
+                                  device->name, session->name, strerror(-r));
         }
-
-        if (error < 0)
-                log_debug("sysview: error while adding device '%s': %s",
-                          device->name, strerror(-r));
-        return error;
 }
 
-static int context_remove_device(sysview_context *c, sysview_device *device) {
+static void context_remove_device(sysview_context *c, sysview_device *device) {
         sysview_session *session;
-        int r, error = 0;
         Iterator i;
+        int r;
 
         assert(c);
         assert(device);
@@ -589,21 +590,18 @@ static int context_remove_device(sysview_context *c, sysview_device *device) {
                         continue;
 
                 r = context_raise_session_detach(c, session, device);
-                if (r != 0)
-                        error = r;
+                if (r < 0)
+                        log_debug("sysview: callback failed while detaching device '%s' from session '%s': %s",
+                                  device->name, session->name, strerror(-r));
         }
 
-        if (error < 0)
-                log_debug("sysview: error while removing device '%s': %s",
-                          device->name, strerror(-r));
         sysview_device_free(device);
-        return error;
 }
 
-static int context_change_device(sysview_context *c, sysview_device *device, struct udev_device *ud) {
+static void context_change_device(sysview_context *c, sysview_device *device, struct udev_device *ud) {
         sysview_session *session;
-        int r, error = 0;
         Iterator i;
+        int r;
 
         assert(c);
         assert(device);
@@ -615,21 +613,17 @@ static int context_change_device(sysview_context *c, sysview_device *device, str
                         continue;
 
                 r = context_raise_session_refresh(c, session, device, ud);
-                if (r != 0)
-                        error = r;
+                if (r < 0)
+                        log_debug("sysview: callback failed while changing device '%s' on session '%s': %s",
+                                  device->name, session->name, strerror(-r));
         }
-
-        if (error < 0)
-                log_debug("sysview: error while changing device '%s': %s",
-                          device->name, strerror(-r));
-        return error;
 }
 
-static int context_add_session(sysview_context *c, sysview_seat *seat, const char *id) {
+static void context_add_session(sysview_context *c, sysview_seat *seat, const char *id) {
         sysview_session *session;
         sysview_device *device;
-        int r, error = 0;
         Iterator i;
+        int r;
 
         assert(c);
         assert(seat);
@@ -637,7 +631,7 @@ static int context_add_session(sysview_context *c, sysview_seat *seat, const cha
 
         session = sysview_find_session(c, id);
         if (session)
-                return 0;
+                return;
 
         log_debug("sysview: add session '%s' on seat '%s'", id, seat->name);
 
@@ -654,35 +648,33 @@ static int context_add_session(sysview_context *c, sysview_seat *seat, const cha
         if (seat->public) {
                 session->public = true;
                 r = context_raise_session_add(c, session);
-                if (r != 0) {
+                if (r < 0) {
+                        log_debug("sysview: callback failed while adding session '%s': %s",
+                                  session->name, strerror(-r));
                         session->public = false;
                         goto error;
                 }
 
                 HASHMAP_FOREACH(device, seat->device_map, i) {
                         r = context_raise_session_attach(c, session, device);
-                        if (r != 0)
-                                error = r;
+                        if (r < 0)
+                                log_debug("sysview: callback failed while attaching device '%s' to new session '%s': %s",
+                                          device->name, session->name, strerror(-r));
                 }
-
-                r = error;
-                if (r != 0)
-                        goto error;
         }
 
-        return 0;
+        return;
 
 error:
         if (r < 0)
                 log_debug("sysview: error while adding session '%s': %s",
                           id, strerror(-r));
-        return r;
 }
 
-static int context_remove_session(sysview_context *c, sysview_session *session) {
+static void context_remove_session(sysview_context *c, sysview_session *session) {
         sysview_device *device;
-        int r, error = 0;
         Iterator i;
+        int r;
 
         assert(c);
         assert(session);
@@ -692,27 +684,25 @@ static int context_remove_session(sysview_context *c, sysview_session *session)
         if (session->public) {
                 HASHMAP_FOREACH(device, session->seat->device_map, i) {
                         r = context_raise_session_detach(c, session, device);
-                        if (r != 0)
-                                error = r;
+                        if (r < 0)
+                                log_debug("sysview: callback failed while detaching device '%s' from old session '%s': %s",
+                                          device->name, session->name, strerror(-r));
                 }
 
                 session->public = false;
                 r = context_raise_session_remove(c, session);
-                if (r != 0)
-                        error = r;
+                if (r < 0)
+                        log_debug("sysview: callback failed while removing session '%s': %s",
+                                  session->name, strerror(-r));
         }
 
         if (!session->custom)
                 sysview_session_release_control(session);
 
-        if (error < 0)
-                log_debug("sysview: error while removing session '%s': %s",
-                          session->name, strerror(-error));
         sysview_session_free(session);
-        return error;
 }
 
-static int context_add_seat(sysview_context *c, const char *id) {
+static void context_add_seat(sysview_context *c, const char *id) {
         sysview_seat *seat;
         int r;
 
@@ -721,7 +711,7 @@ static int context_add_seat(sysview_context *c, const char *id) {
 
         seat = sysview_find_seat(c, id);
         if (seat)
-                return 0;
+                return;
 
         log_debug("sysview: add seat '%s'", id);
 
@@ -731,54 +721,45 @@ static int context_add_seat(sysview_context *c, const char *id) {
 
         seat->public = true;
         r = context_raise_seat_add(c, seat);
-        if (r != 0) {
+        if (r < 0) {
+                log_debug("sysview: callback failed while adding seat '%s': %s",
+                          seat->name, strerror(-r));
                 seat->public = false;
-                goto error;
         }
 
-        return 0;
+        return;
 
 error:
         if (r < 0)
                 log_debug("sysview: error while adding seat '%s': %s",
                           id, strerror(-r));
-        return r;
 }
 
-static int context_remove_seat(sysview_context *c, sysview_seat *seat) {
+static void context_remove_seat(sysview_context *c, sysview_seat *seat) {
         sysview_session *session;
         sysview_device *device;
-        int r, error = 0;
+        int r;
 
         assert(c);
         assert(seat);
 
         log_debug("sysview: remove seat '%s'", seat->name);
 
-        while ((device = hashmap_first(seat->device_map))) {
-                r = context_remove_device(c, device);
-                if (r != 0)
-                        error = r;
-        }
+        while ((device = hashmap_first(seat->device_map)))
+                context_remove_device(c, device);
 
-        while ((session = hashmap_first(seat->session_map))) {
-                r = context_remove_session(c, session);
-                if (r != 0)
-                        error = r;
-        }
+        while ((session = hashmap_first(seat->session_map)))
+                context_remove_session(c, session);
 
         if (seat->public) {
                 seat->public = false;
                 r = context_raise_seat_remove(c, seat);
-                if (r != 0)
-                        error = r;
+                if (r < 0)
+                        log_debug("sysview: callback failed while removing seat '%s': %s",
+                                  seat->name, strerror(-r));
         }
 
-        if (error < 0)
-                log_debug("sysview: error while removing seat '%s': %s",
-                          seat->name, strerror(-error));
         sysview_seat_free(seat);
-        return error;
 }
 
 int sysview_context_new(sysview_context **out,
@@ -923,12 +904,12 @@ static int context_ud_hotplug(sysview_context *c, struct udev_device *d) {
                 if (!device)
                         return 0;
 
-                return context_remove_device(c, device);
+                context_remove_device(c, device);
         } else if (streq_ptr(action, "change")) {
                 if (!device)
                         return 0;
 
-                return context_change_device(c, device, d);
+                context_change_device(c, device, d);
         } else if (!action || streq_ptr(action, "add")) {
                 struct udev_device *p;
                 unsigned int type, t;
@@ -966,7 +947,7 @@ static int context_ud_hotplug(sysview_context *c, struct udev_device *d) {
                         return r;
                 }
 
-                return context_add_device(c, device);
+                context_add_device(c, device);
         }
 
         return 0;
@@ -1093,7 +1074,8 @@ static int context_ld_seat_new(sysview_context *c, sd_bus_message *signal) {
                 return r;
         }
 
-        return context_add_seat(c, id);
+        context_add_seat(c, id);
+        return 0;
 }
 
 static int context_ld_seat_removed(sysview_context *c, sd_bus_message *signal) {
@@ -1112,7 +1094,8 @@ static int context_ld_seat_removed(sysview_context *c, sd_bus_message *signal) {
         if (!seat)
                 return 0;
 
-        return context_remove_seat(c, seat);
+        context_remove_seat(c, seat);
+        return 0;
 }
 
 static int context_ld_session_new(sysview_context *c, sd_bus_message *signal) {
@@ -1159,14 +1142,13 @@ static int context_ld_session_new(sysview_context *c, sd_bus_message *signal) {
         }
 
         r = context_raise_session_filter(c, id, seatid, username, uid);
-        if (r <= 0) {
-                if (r < 0)
-                        log_debug("sysview: cannot filter new session '%s' on seat '%s': %s",
-                                  id, seatid, strerror(-r));
-                return r;
-        }
+        if (r < 0)
+                log_debug("sysview: callback failed while filtering session '%s': %s",
+                          id, strerror(-r));
+        else if (r > 0)
+                context_add_session(c, seat, id);
 
-        return context_add_session(c, seat, id);
+        return 0;
 
 error:
         log_debug("sysview: failed retrieving information for new session '%s': %s",
@@ -1190,7 +1172,8 @@ static int context_ld_session_removed(sysview_context *c, sd_bus_message *signal
         if (!session)
                 return 0;
 
-        return context_remove_session(c, session);
+        context_remove_session(c, session);
+        return 0;
 }
 
 static int context_ld_manager_signal_fn(sd_bus *bus,
@@ -1265,9 +1248,7 @@ static int context_ld_list_seats_fn(sd_bus *bus,
                 if (r < 0)
                         goto error;
 
-                r = context_add_seat(c, id);
-                if (r != 0)
-                        return r;
+                context_add_seat(c, id);
 
                 r = sd_bus_message_exit_container(reply);
                 if (r < 0)
@@ -1328,15 +1309,11 @@ static int context_ld_list_sessions_fn(sd_bus *bus,
                 seat = sysview_find_seat(c, seatid);
                 if (seat) {
                         r = context_raise_session_filter(c, id, seatid, username, uid);
-                        if (r < 0) {
-                                log_debug("sysview: cannot filter listed session '%s' on seat '%s': %s",
-                                          id, seatid, strerror(-r));
-                                return r;
-                        } else if (r > 0) {
-                                r = context_add_session(c, seat, id);
-                                if (r != 0)
-                                        return r;
-                        }
+                        if (r < 0)
+                                log_debug("sysview: callback failed while filtering session '%s': %s",
+                                          id, strerror(-r));
+                        else if (r > 0)
+                                context_add_session(c, seat, id);
                 }
 
                 r = sd_bus_message_exit_container(reply);

commit f2a15d86ccd0729e1442f40679cd393417e1e177
Author: David Herrmann <dh.herrmann at gmail.com>
Date:   Mon Sep 22 17:37:21 2014 +0200

    terminal: allow user-context to be retrieved/stored
    
    Add "userdata" storage to a bunch of external objects, namely displays and
    sessions. Furthermore, add some property retrieval helpers.
    
    This is required if we want external API users to not duplicate our own
    object hashtables, but retrieve context from the objects themselves.

diff --git a/src/libsystemd-terminal/grdev-internal.h b/src/libsystemd-terminal/grdev-internal.h
index f5915b1..ee18269 100644
--- a/src/libsystemd-terminal/grdev-internal.h
+++ b/src/libsystemd-terminal/grdev-internal.h
@@ -94,6 +94,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(grdev_tile*, grdev_tile_free);
 struct grdev_display {
         grdev_session *session;
         char *name;
+        void *userdata;
 
         size_t n_leafs;
         grdev_tile *tile;
diff --git a/src/libsystemd-terminal/grdev.c b/src/libsystemd-terminal/grdev.c
index 43d0c7c..e34112e 100644
--- a/src/libsystemd-terminal/grdev.c
+++ b/src/libsystemd-terminal/grdev.c
@@ -282,6 +282,24 @@ grdev_display *grdev_display_free(grdev_display *display) {
         return NULL;
 }
 
+void grdev_display_set_userdata(grdev_display *display, void *userdata) {
+        assert(display);
+
+        display->userdata = userdata;
+}
+
+void *grdev_display_get_userdata(grdev_display *display) {
+        assert_return(display, NULL);
+
+        return display->userdata;
+}
+
+const char *grdev_display_get_name(grdev_display *display) {
+        assert_return(display, NULL);
+
+        return display->name;
+}
+
 bool grdev_display_is_enabled(grdev_display *display) {
         return display && display->enabled;
 }
diff --git a/src/libsystemd-terminal/grdev.h b/src/libsystemd-terminal/grdev.h
index 9924a25..5f745aa 100644
--- a/src/libsystemd-terminal/grdev.h
+++ b/src/libsystemd-terminal/grdev.h
@@ -108,6 +108,11 @@ struct grdev_display_target {
         const grdev_fb *fb;
 };
 
+void grdev_display_set_userdata(grdev_display *display, void *userdata);
+void *grdev_display_get_userdata(grdev_display *display);
+
+const char *grdev_display_get_name(grdev_display *display);
+
 bool grdev_display_is_enabled(grdev_display *display);
 void grdev_display_enable(grdev_display *display);
 void grdev_display_disable(grdev_display *display);
diff --git a/src/libsystemd-terminal/sysview-internal.h b/src/libsystemd-terminal/sysview-internal.h
index 9299fab..d9f7fe3 100644
--- a/src/libsystemd-terminal/sysview-internal.h
+++ b/src/libsystemd-terminal/sysview-internal.h
@@ -64,6 +64,7 @@ struct sysview_session {
         sysview_seat *seat;
         char *name;
         char *path;
+        void *userdata;
 
         sd_bus_slot *slot_take_control;
 
diff --git a/src/libsystemd-terminal/sysview.c b/src/libsystemd-terminal/sysview.c
index 5b623c1..208c6ce 100644
--- a/src/libsystemd-terminal/sysview.c
+++ b/src/libsystemd-terminal/sysview.c
@@ -104,6 +104,12 @@ sysview_device *sysview_device_free(sysview_device *device) {
         return NULL;
 }
 
+const char *sysview_device_get_name(sysview_device *device) {
+        assert_return(device, NULL);
+
+        return device->name;
+}
+
 unsigned int sysview_device_get_type(sysview_device *device) {
         assert_return(device, (unsigned)-1);
 
@@ -243,6 +249,18 @@ sysview_session *sysview_session_free(sysview_session *session) {
         return NULL;
 }
 
+void sysview_session_set_userdata(sysview_session *session, void *userdata) {
+        assert(session);
+
+        session->userdata = userdata;
+}
+
+void *sysview_session_get_userdata(sysview_session *session) {
+        assert_return(session, NULL);
+
+        return session->userdata;
+}
+
 const char *sysview_session_get_name(sysview_session *session) {
         assert_return(session, NULL);
 
diff --git a/src/libsystemd-terminal/sysview.h b/src/libsystemd-terminal/sysview.h
index 4d800f8..f691e49 100644
--- a/src/libsystemd-terminal/sysview.h
+++ b/src/libsystemd-terminal/sysview.h
@@ -116,6 +116,7 @@ enum {
         SYSVIEW_DEVICE_CNT
 };
 
+const char *sysview_device_get_name(sysview_device *device);
 unsigned int sysview_device_get_type(sysview_device *device);
 struct udev_device *sysview_device_get_ud(sysview_device *device);
 
@@ -123,6 +124,9 @@ struct udev_device *sysview_device_get_ud(sysview_device *device);
  * Sessions
  */
 
+void sysview_session_set_userdata(sysview_session *session, void *userdata);
+void *sysview_session_get_userdata(sysview_session *session);
+
 const char *sysview_session_get_name(sysview_session *session);
 
 int sysview_session_take_control(sysview_session *session);

commit 5d301b8aecc286d6ec7e92b0864d66360ea57205
Author: David Herrmann <dh.herrmann at gmail.com>
Date:   Mon Sep 22 17:34:13 2014 +0200

    terminal: make evdev logind-matches per session
    
    Instead of adding matches per device, we now add logind matches per
    session. This reduces the number of matches considerably and saves
    resources.

diff --git a/src/libsystemd-terminal/idev-evdev.c b/src/libsystemd-terminal/idev-evdev.c
index 719e18c..63fa89e 100644
--- a/src/libsystemd-terminal/idev-evdev.c
+++ b/src/libsystemd-terminal/idev-evdev.c
@@ -60,9 +60,6 @@ struct unmanaged_evdev {
 struct managed_evdev {
         idev_evdev evdev;
         dev_t devnum;
-
-        sd_bus_slot *slot_pause_device;
-        sd_bus_slot *slot_resume_device;
         sd_bus_slot *slot_take_device;
 
         bool requested : 1;             /* TakeDevice() was sent */
@@ -580,7 +577,7 @@ static int managed_evdev_take_device_fn(sd_bus *bus,
         return 0;
 }
 
-static void managed_evdev_resume(idev_element *e) {
+static void managed_evdev_enable(idev_element *e) {
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
         managed_evdev *em = managed_evdev_from_element(e);
         idev_session *s = e->session;
@@ -628,7 +625,7 @@ error:
                   s->name, e->name, strerror(-r));
 }
 
-static void managed_evdev_pause(idev_element *e) {
+static void managed_evdev_disable(idev_element *e) {
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
         managed_evdev *em = managed_evdev_from_element(e);
         idev_session *s = e->session;
@@ -686,24 +683,45 @@ static void managed_evdev_pause(idev_element *e) {
                           s->name, e->name, strerror(-r));
 }
 
-static int managed_evdev_pause_device_fn(sd_bus *bus,
-                                         sd_bus_message *signal,
-                                         void *userdata,
-                                         sd_bus_error *ret_error) {
-        managed_evdev *em = userdata;
-        idev_element *e = &em->evdev.element;
+static void managed_evdev_resume(idev_element *e, int fd) {
+        managed_evdev *em = managed_evdev_from_element(e);
+        idev_session *s = e->session;
+        int r;
+
+        /*
+         * We get ResumeDevice signals whenever logind resumed a previously
+         * paused device. The arguments contain the major/minor number of the
+         * related device and a new file-descriptor for the freshly opened
+         * device-node. We take the file-descriptor and immediately resume the
+         * device.
+         */
+
+        fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+        if (fd < 0) {
+                log_debug("idev-evdev: %s/%s: cannot duplicate evdev fd: %m",
+                          s->name, e->name);
+                return;
+        }
+
+        r = idev_evdev_resume(&em->evdev, fd);
+        if (r < 0)
+                log_debug("idev-evdev: %s/%s: cannot resume: %s",
+                          s->name, e->name, strerror(-r));
+
+        return;
+}
+
+static void managed_evdev_pause(idev_element *e, const char *mode) {
+        managed_evdev *em = managed_evdev_from_element(e);
         idev_session *s = e->session;
         idev_context *c = s->context;
-        uint32_t major, minor;
-        const char *mode;
         int r;
 
         /*
          * We get PauseDevice() signals from logind whenever a device we
          * requested was, or is about to be, paused. Arguments are major/minor
          * number of the device and the mode of the operation.
-         * In case the event is not about our device, we ignore it. Otherwise,
-         * we treat it as asynchronous access-revocation (as if we got HUP on
+         * We treat it as asynchronous access-revocation (as if we got HUP on
          * the device fd). Note that we might have already treated the HUP
          * event via EPOLLHUP, whichever comes first.
          *
@@ -728,17 +746,6 @@ static int managed_evdev_pause_device_fn(sd_bus *bus,
          * acknowledge the request.
          */
 
-        r = sd_bus_message_read(signal, "uus", &major, &minor, &mode);
-        if (r < 0) {
-                log_debug("idev-evdev: %s/%s: erroneous PauseDevice signal",
-                          s->name, e->name);
-                return 0;
-        }
-
-        /* not our device? */
-        if (makedev(major, minor) != em->devnum)
-                return 0;
-
         idev_evdev_pause(&em->evdev, true);
 
         if (streq(mode, "pause")) {
@@ -763,7 +770,7 @@ static int managed_evdev_pause_device_fn(sd_bus *bus,
                                                    "org.freedesktop.login1.Session",
                                                    "PauseDeviceComplete");
                 if (r >= 0) {
-                        r = sd_bus_message_append(m, "uu", major, minor);
+                        r = sd_bus_message_append(m, "uu", major(em->devnum), minor(em->devnum));
                         if (r >= 0)
                                 r = sd_bus_send(c->sysbus, m, NULL);
                 }
@@ -772,99 +779,6 @@ static int managed_evdev_pause_device_fn(sd_bus *bus,
                         log_debug("idev-evdev: %s/%s: cannot send PauseDeviceComplete: %s",
                                   s->name, e->name, strerror(-r));
         }
-
-        return 0;
-}
-
-static int managed_evdev_resume_device_fn(sd_bus *bus,
-                                          sd_bus_message *signal,
-                                          void *userdata,
-                                          sd_bus_error *ret_error) {
-        managed_evdev *em = userdata;
-        idev_element *e = &em->evdev.element;
-        idev_session *s = e->session;
-        uint32_t major, minor;
-        int r, fd;
-
-        /*
-         * We get ResumeDevice signals whenever logind resumed a previously
-         * paused device. The arguments contain the major/minor number of the
-         * related device and a new file-descriptor for the freshly opened
-         * device-node.
-         * If the signal is not about our device, we simply ignore it.
-         * Otherwise, we take the file-descriptor and immediately resume the
-         * device.
-         */
-
-        r = sd_bus_message_read(signal, "uuh", &major, &minor, &fd);
-        if (r < 0) {
-                log_debug("idev-evdev: %s/%s: erroneous ResumeDevice signal",
-                          s->name, e->name);
-                return 0;
-        }
-
-        /* not our device? */
-        if (makedev(major, minor) != em->devnum)
-                return 0;
-
-        fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
-        if (fd < 0) {
-                log_debug("idev-evdev: %s/%s: cannot duplicate evdev fd: %m",
-                          s->name, e->name);
-                return 0;
-        }
-
-        r = idev_evdev_resume(&em->evdev, fd);
-        if (r < 0)
-                log_debug("idev-evdev: %s/%s: cannot resume: %s",
-                          s->name, e->name, strerror(-r));
-
-        return 0;
-}
-
-static int managed_evdev_setup_bus(managed_evdev *em) {
-        idev_element *e = &em->evdev.element;
-        idev_session *s = e->session;
-        idev_context *c = s->context;
-        _cleanup_free_ char *match = NULL;
-        int r;
-
-        match = strjoin("type='signal',"
-                        "sender='org.freedesktop.login1',"
-                        "interface='org.freedesktop.login1.Session',"
-                        "member='PauseDevice',"
-                        "path='", s->path, "'",
-                        NULL);
-        if (!match)
-                return -ENOMEM;
-
-        r = sd_bus_add_match(c->sysbus,
-                             &em->slot_pause_device,
-                             match,
-                             managed_evdev_pause_device_fn,
-                             em);
-        if (r < 0)
-                return r;
-
-        free(match);
-        match = strjoin("type='signal',"
-                        "sender='org.freedesktop.login1',"
-                        "interface='org.freedesktop.login1.Session',"
-                        "member='ResumeDevice',"
-                        "path='", s->path, "'",
-                        NULL);
-        if (!match)
-                return -ENOMEM;
-
-        r = sd_bus_add_match(c->sysbus,
-                             &em->slot_resume_device,
-                             match,
-                             managed_evdev_resume_device_fn,
-                             em);
-        if (r < 0)
-                return r;
-
-        return 0;
 }
 
 static int managed_evdev_new(idev_element **out, idev_session *s, struct udev_device *ud) {
@@ -893,10 +807,6 @@ static int managed_evdev_new(idev_element **out, idev_session *s, struct udev_de
         em->evdev = IDEV_EVDEV_INIT(&managed_evdev_vtable, s);
         em->devnum = devnum;
 
-        r = managed_evdev_setup_bus(em);
-        if (r < 0)
-                return r;
-
         r = idev_element_add(e, name);
         if (r < 0)
                 return r;
@@ -910,18 +820,18 @@ static int managed_evdev_new(idev_element **out, idev_session *s, struct udev_de
 static void managed_evdev_free(idev_element *e) {
         managed_evdev *em = managed_evdev_from_element(e);
 
-        em->slot_resume_device = sd_bus_slot_unref(em->slot_resume_device);
-        em->slot_pause_device = sd_bus_slot_unref(em->slot_pause_device);
         idev_evdev_destroy(&em->evdev);
         free(em);
 }
 
 static const idev_element_vtable managed_evdev_vtable = {
         .free                   = managed_evdev_free,
-        .enable                 = managed_evdev_resume,
-        .disable                = managed_evdev_pause,
-        .open                   = managed_evdev_resume,
-        .close                  = managed_evdev_pause,
+        .enable                 = managed_evdev_enable,
+        .disable                = managed_evdev_disable,
+        .open                   = managed_evdev_enable,
+        .close                  = managed_evdev_disable,
+        .resume                 = managed_evdev_resume,
+        .pause                  = managed_evdev_pause,
 };
 
 /*
diff --git a/src/libsystemd-terminal/idev-internal.h b/src/libsystemd-terminal/idev-internal.h
index c416f4f..a159aef 100644
--- a/src/libsystemd-terminal/idev-internal.h
+++ b/src/libsystemd-terminal/idev-internal.h
@@ -116,6 +116,8 @@ struct idev_element_vtable {
         void (*disable) (idev_element *e);
         void (*open) (idev_element *e);
         void (*close) (idev_element *e);
+        void (*resume) (idev_element *e, int fd);
+        void (*pause) (idev_element *e, const char *mode);
         void (*feedback) (idev_element *e, idev_data *data);
 };
 
@@ -155,6 +157,8 @@ struct idev_session {
         idev_context *context;
         char *name;
         char *path;
+        sd_bus_slot *slot_resume_device;
+        sd_bus_slot *slot_pause_device;
 
         Hashmap *element_map;
         Hashmap *device_map;
diff --git a/src/libsystemd-terminal/idev.c b/src/libsystemd-terminal/idev.c
index 8592930..e979b60 100644
--- a/src/libsystemd-terminal/idev.c
+++ b/src/libsystemd-terminal/idev.c
@@ -274,6 +274,22 @@ static void element_disable(idev_element *e) {
         }
 }
 
+static void element_resume(idev_element *e, int fd) {
+        assert(e);
+        assert(fd >= 0);
+
+        if (e->vtable->resume)
+                e->vtable->resume(e, fd);
+}
+
+static void element_pause(idev_element *e, const char *mode) {
+        assert(e);
+        assert(mode);
+
+        if (e->vtable->pause)
+                e->vtable->pause(e, mode);
+}
+
 /*
  * Sessions
  */
@@ -417,6 +433,98 @@ idev_session *idev_find_session(idev_context *c, const char *name) {
         return hashmap_get(c->session_map, name);
 }
 
+static int session_resume_device_fn(sd_bus *bus,
+                                    sd_bus_message *signal,
+                                    void *userdata,
+                                    sd_bus_error *ret_error) {
+        idev_session *s = userdata;
+        idev_element *e;
+        uint32_t major, minor;
+        int r, fd;
+
+        r = sd_bus_message_read(signal, "uuh", &major, &minor, &fd);
+        if (r < 0) {
+                log_debug("idev: %s: erroneous ResumeDevice signal", s->name);
+                return 0;
+        }
+
+        e = idev_find_evdev(s, makedev(major, minor));
+        if (!e)
+                return 0;
+
+        element_resume(e, fd);
+        return 0;
+}
+
+static int session_pause_device_fn(sd_bus *bus,
+                                   sd_bus_message *signal,
+                                   void *userdata,
+                                   sd_bus_error *ret_error) {
+        idev_session *s = userdata;
+        idev_element *e;
+        uint32_t major, minor;
+        const char *mode;
+        int r;
+
+        r = sd_bus_message_read(signal, "uus", &major, &minor, &mode);
+        if (r < 0) {
+                log_debug("idev: %s: erroneous PauseDevice signal", s->name);
+                return 0;
+        }
+
+        e = idev_find_evdev(s, makedev(major, minor));
+        if (!e)
+                return 0;
+
+        element_pause(e, mode);
+        return 0;
+}
+
+static int session_setup_bus(idev_session *s) {
+        _cleanup_free_ char *match = NULL;
+        int r;
+
+        if (!s->managed)
+                return 0;
+
+        match = strjoin("type='signal',"
+                        "sender='org.freedesktop.login1',"
+                        "interface='org.freedesktop.login1.Session',"
+                        "member='ResumeDevice',"
+                        "path='", s->path, "'",
+                        NULL);
+        if (!match)
+                return -ENOMEM;
+
+        r = sd_bus_add_match(s->context->sysbus,
+                             &s->slot_resume_device,
+                             match,
+                             session_resume_device_fn,
+                             s);
+        if (r < 0)
+                return r;
+
+        free(match);
+        match = strjoin("type='signal',"
+                        "sender='org.freedesktop.login1',"
+                        "interface='org.freedesktop.login1.Session',"
+                        "member='PauseDevice',"
+                        "path='", s->path, "'",
+                        NULL);
+        if (!match)
+                return -ENOMEM;
+
+        r = sd_bus_add_match(s->context->sysbus,
+                             &s->slot_pause_device,
+                             match,
+                             session_pause_device_fn,
+                             s);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 int idev_session_new(idev_session **out,
                      idev_context *c,
                      unsigned int flags,
@@ -462,6 +570,10 @@ int idev_session_new(idev_session **out,
         if (!s->device_map)
                 return -ENOMEM;
 
+        r = session_setup_bus(s);
+        if (r < 0)
+                return r;
+
         r = hashmap_put(c->session_map, s->name, s);
         if (r < 0)
                 return r;
@@ -485,6 +597,8 @@ idev_session *idev_session_free(idev_session *s) {
         if (s->name)
                 hashmap_remove_value(s->context->session_map, s->name, s);
 
+        s->slot_pause_device = sd_bus_slot_unref(s->slot_pause_device);
+        s->slot_resume_device = sd_bus_slot_unref(s->slot_resume_device);
         s->context = idev_context_unref(s->context);
         hashmap_free(s->device_map);
         hashmap_free(s->element_map);



More information about the systemd-commits mailing list