[Spice-devel] [vdagent-linux v3 2/4] console-kit: implement check for locked session

Jonathon Jongsma jjongsma at redhat.com
Fri Apr 29 15:08:53 UTC 2016


On Thu, 2016-04-28 at 15:37 +0200, Victor Toso wrote:
> We register to read the Lock, Unlock and IdleHintChanged signals from
> ConsoleKit.Session. The Lock/Unlock signals should be the right
> signals for the job but not all Desktop Managers implement its locking
> in a way that trigger those signals. That's why we double-check with
> IdleHintChanged signal that it might be triggered by other services
> like screen savers.
> 
> Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
> ---
>  src/console-kit.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> -
>  1 file changed, 82 insertions(+), 3 deletions(-)
> 
> diff --git a/src/console-kit.c b/src/console-kit.c
> index 72a5b16..b21df6f 100644
> --- a/src/console-kit.c
> +++ b/src/console-kit.c
> @@ -35,6 +35,9 @@ struct session_info {
>      char *active_session;
>      int verbose;
>      gchar *match_seat_signals;
> +    gchar *match_session_signals;
> +    gboolean session_is_locked;
> +    gboolean session_idle_hint;
>  };
>  
>  #define INTERFACE_CONSOLE_KIT "org.freedesktop.ConsoleKit"
> @@ -45,8 +48,15 @@ struct session_info {
>  
>  #define INTERFACE_CONSOLE_KIT_SEAT       INTERFACE_CONSOLE_KIT ".Seat"
>  
> +#define INTERFACE_CONSOLE_KIT_SESSION    INTERFACE_CONSOLE_KIT ".Session"
> +#define OBJ_PATH_CONSOLE_KIT_SESSION     OBJ_PATH_CONSOLE_KIT "/Session"
> +
>  #define SEAT_SIGNAL_ACTIVE_SESSION_CHANGED       "ActiveSessionChanged"
>  
> +#define SESSION_SIGNAL_LOCK                      "Lock"
> +#define SESSION_SIGNAL_UNLOCK                    "Unlock"
> +#define SESSION_SIGNAL_IDLE_HINT_CHANGED         "IdleHintChanged"
> +
>  static char *console_kit_get_first_seat(struct session_info *info);
>  static char *console_kit_check_active_session_change(struct session_info
> *info);
>  
> @@ -64,6 +74,19 @@ static void si_dbus_match_remove(struct session_info *info)
>          g_free(info->match_seat_signals);
>          info->match_seat_signals = NULL;
>      }
> +
> +    if (info->match_session_signals != NULL) {
> +        dbus_error_init(&error);
> +        dbus_bus_remove_match(info->connection,
> +                              info->match_session_signals,
> +                              &error);
> +
> +        if (info->verbose)
> +            syslog(LOG_DEBUG, "(console-kit) session match removed: %s",
> +                   info->match_session_signals);
> +        g_free(info->match_session_signals);
> +        info->match_session_signals = NULL;
> +    }
>  }
>  
>  static void si_dbus_match_rule_update(struct session_info *info)
> @@ -97,6 +120,28 @@ static void si_dbus_match_rule_update(struct session_info
> *info)
>              g_free(info->match_seat_signals);
>          }
>      }
> +
> +    /* Session signals */
> +    if (info->active_session != NULL) {
> +        info->match_session_signals =
> +            g_strdup_printf ("type='signal',interface='%s',path='%s'",
> +                             INTERFACE_CONSOLE_KIT_SESSION,
> +                             info->active_session);
> +        if (info->verbose)
> +            syslog(LOG_DEBUG, "(console-kit) session match: %s",
> +                   info->match_session_signals);
> +
> +        dbus_error_init(&error);
> +        dbus_bus_add_match(info->connection,
> +                           info->match_session_signals,
> +                           &error);
> +        if (dbus_error_is_set(&error)) {
> +            syslog(LOG_WARNING, "Unable to add dbus rule match: %s",
> +                   error.message);
> +            dbus_error_free(&error);
> +            g_free(info->match_session_signals);

Dangling pointer. Set to NULL.

> +        }
> +    }
>  }
>  
>  static void
> @@ -133,6 +178,7 @@ si_dbus_read_signals(struct session_info *info)
>                  dbus_message_iter_get_basic(&iter, &session);
>                  if (session != NULL && session[0] != '\0') {
>                      info->active_session = g_strdup(session);
> +                    si_dbus_match_rule_update(info);
>                  } else {
>                      syslog(LOG_WARNING, "(console-kit) received invalid
> session. "
>                             "No active-session at the moment");
> @@ -142,6 +188,25 @@ si_dbus_read_signals(struct session_info *info)
>                         "ActiveSessionChanged message has unexpected type:
> '%c'",
>                         type);
>              }
> +        } else if (g_strcmp0(member, SESSION_SIGNAL_LOCK) == 0) {
> +            info->session_is_locked = TRUE;
> +        } else if (g_strcmp0(member, SESSION_SIGNAL_UNLOCK) == 0) {
> +            info->session_is_locked = FALSE;
> +        } else if (g_strcmp0(member, SESSION_SIGNAL_IDLE_HINT_CHANGED) == 0)
> {
> +            DBusMessageIter iter;
> +            gint type;
> +            dbus_bool_t idle_hint;
> +
> +            dbus_message_iter_init(message, &iter);
> +            type = dbus_message_iter_get_arg_type(&iter);
> +            if (type == DBUS_TYPE_BOOLEAN) {
> +                dbus_message_iter_get_basic(&iter, &idle_hint);
> +                info->session_idle_hint = (idle_hint);
> +            } else {
> +                syslog(LOG_ERR,
> +                       "(console-kit) IdleHintChanged has unexpected type:
> '%c'",
> +                       type);
> +            }
>          } else if (info->verbose) {
>              syslog(LOG_DEBUG, "(console-kit) Signal not handled: %s",
> member);
>          }
> @@ -162,6 +227,8 @@ struct session_info *session_info_create(int verbose)
>          return NULL;
>  
>      info->verbose = verbose;
> +    info->session_is_locked = FALSE;
> +    info->session_idle_hint = FALSE;
>  
>      dbus_error_init(&error);
>      info->connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
> @@ -324,6 +391,7 @@ const char *session_info_get_active_session(struct
> session_info *info)
>      }
>  
>      info->active_session = strdup(session);
> +    si_dbus_match_rule_update(info);
>  
>  exit:
>      if (reply != NULL) {
> @@ -419,7 +487,18 @@ static char
> *console_kit_check_active_session_change(struct session_info *info)
>  
>  gboolean session_info_session_is_locked(struct session_info *info)
>  {
> -    /* TODO: It could be implemented based on Lock/Unlock signals from
> Session
> -     * interface. */
> -    return FALSE;
> +    if (info == NULL)
> +        return FALSE;

This seems like an unexpected situation? Perhaps use something like
g_return_val_if_fail()? Do we really want to default to reporting 'unlocked' in
this scenario? reporting it as 'locked' seems somewhat safer

> +
> +    /* Not every system does emit Lock and Unlock signals (for instance, such
> +     * is the case for RHEL6) but most of the systems seems to emit the
> +     * IdleHintChanged. So, we give priority to the Lock signal, if it is
> Locked
> +     * we return that the session is locked, otherwise we double check with
> the
> +     * IdleHint value */
> +    si_dbus_read_signals(info);
> +    if (info->verbose) {
> +        syslog(LOG_DEBUG, "(console-kit) session is locked: %s",
> +               (info->session_is_locked || info->session_idle_hint) ? "yes" :
> "no");
> +    }
> +    return (info->session_is_locked || info->session_idle_hint);

Personal preference. I'd introduce a local boolean variable here so that you
don't need to repeat the (info->session_is_locked || info->session_idle_hint)
twice (once for the debug statement and once for the return value)


Reviewed-by: Jonathon Jongsma <jjongsma at redhat.com>


More information about the Spice-devel mailing list