diff options
| author | William Jon McCann <mccann@jhu.edu> | 2007-03-05 11:18:32 -0500 | 
|---|---|---|
| committer | William Jon McCann <mccann@jhu.edu> | 2007-03-05 11:18:32 -0500 | 
| commit | 67fa39aacf65117a85533035a71ee09b184003dc (patch) | |
| tree | ab01c3d33071b2ccfaa83bcb96a0df177ab72101 /src | |
| parent | f67761a042ff8b29d7689a043a53110d0bbbf6e9 (diff) | |
use an async job to collect session info
Use an async helper job to collect session info for the
OpenSession() method.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/ck-job.c | 392 | ||||
| -rw-r--r-- | src/ck-job.h | 76 | ||||
| -rw-r--r-- | src/ck-manager.c | 278 | 
4 files changed, 672 insertions, 76 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 1835ecd..5f18cc7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,6 +58,8 @@ console_kit_daemon_SOURCES =	\  	ck-manager.c		\  	ck-vt-monitor.h		\  	ck-vt-monitor.c		\ +	ck-job.h		\ +	ck-job.c		\  	ck-seat.h		\  	ck-seat.c		\  	ck-session.h		\ diff --git a/src/ck-job.c b/src/ck-job.c new file mode 100644 index 0000000..44e9a57 --- /dev/null +++ b/src/ck-job.c @@ -0,0 +1,392 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> + +#include <glib.h> +#include <glib/gi18n.h> +#include <glib-object.h> + +#include "ck-job.h" +#include "ck-debug.h" +#include "ck-marshal.h" + +#define CK_JOB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_JOB, CkJobPrivate)) + +struct CkJobPrivate +{ +        guint       err_watch_id; +        guint       out_watch_id; + +        char       *command; +        GString    *stdout; +        GString    *stderr; +        GPid        child_pid; + +}; + +enum { +        COMPLETED, +        LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0, }; + +static void     ck_job_class_init  (CkJobClass *klass); +static void     ck_job_init        (CkJob      *job); +static void     ck_job_finalize    (GObject     *object); + +G_DEFINE_TYPE (CkJob, ck_job, G_TYPE_OBJECT) + +GQuark +ck_job_error_quark (void) +{ +        static GQuark ret = 0; +        if (ret == 0) { +                ret = g_quark_from_static_string ("ck_job_error"); +        } + +        return ret; +} + +static int +wait_on_child (int pid) +{ +        int status; + + wait_again: +        if (waitpid (pid, &status, 0) < 0) { +                if (errno == EINTR) { +                        goto wait_again; +                } else if (errno == ECHILD) { +                        ; /* do nothing, child already reaped */ +                } else { +                        ck_debug ("waitpid () should not fail"); +                } +        } + +        return status; +} + +static int +wait_on_job (CkJob *job) +{ +        int status; + +        status = wait_on_child (job->priv->child_pid); + +        g_spawn_close_pid (job->priv->child_pid); +        job->priv->child_pid = 0; + +        return WEXITSTATUS(status); +} + +static void +maybe_complete_job (CkJob *job) +{ +        if (job->priv->out_watch_id == 0 +            && job->priv->err_watch_id == 0) { +                int status; + +                status = wait_on_job (job); + +                ck_debug ("Emitting completed"); +                g_signal_emit (job, signals [COMPLETED], 0, status); +        } +} + +static gboolean +error_watch (GIOChannel   *source, +             GIOCondition  condition, +             CkJob        *job) +{ +        gboolean finished = FALSE; + +        if (condition & G_IO_IN) { +                GIOStatus status; +                GError   *error = NULL; +                char     *line; + +                line = NULL; +                status = g_io_channel_read_line (source, &line, NULL, NULL, &error); + +                switch (status) { +                case G_IO_STATUS_NORMAL: +                        ck_debug ("command error output: %s", line); +                        g_string_append (job->priv->stderr, line); +                        break; +                case G_IO_STATUS_EOF: +                        finished = TRUE; +                        break; +                case G_IO_STATUS_ERROR: +                        finished = TRUE; +                        ck_debug ("Error reading from child: %s\n", error->message); +                        break; +                case G_IO_STATUS_AGAIN: +                default: +                        break; +                } +                g_free (line); +        } else if (condition & G_IO_HUP) { +                finished = TRUE; +        } + +        if (finished) { +                job->priv->err_watch_id = 0; +                maybe_complete_job (job); +                return FALSE; +        } + +        return TRUE; +} + +static gboolean +out_watch (GIOChannel   *source, +           GIOCondition  condition, +           CkJob        *job) +{ +        gboolean finished = FALSE; + +        if (condition & G_IO_IN) { +                GIOStatus status; +                GError   *error = NULL; +                char     *line; + +                line = NULL; +                status = g_io_channel_read_line (source, &line, NULL, NULL, &error); + +                switch (status) { +                case G_IO_STATUS_NORMAL: +                        ck_debug ("command output: %s", line); +                        g_string_append (job->priv->stdout, line); +                        break; +                case G_IO_STATUS_EOF: +                        finished = TRUE; +                        break; +                case G_IO_STATUS_ERROR: +                        finished = TRUE; +                        ck_debug ("Error reading from child: %s\n", error->message); +                        break; +                case G_IO_STATUS_AGAIN: +                default: +                        break; +                } +                g_free (line); +        } else if (condition & G_IO_HUP) { +                finished = TRUE; +        } + +        if (finished) { +                job->priv->out_watch_id = 0; +                maybe_complete_job (job); +                return FALSE; +        } + +        return TRUE; +} + +gboolean +ck_job_execute (CkJob   *job, +                GError **error) +{ +        GError     *local_error; +        gboolean    res; +        GIOChannel *channel; +        int         standard_output; +        int         standard_error; +        int         argc; +        char      **argv; + +        ck_debug ("Executing %s", job->priv->command); +        local_error = NULL; +        if (! g_shell_parse_argv (job->priv->command, &argc, &argv, &local_error)) { +                ck_debug ("Could not parse command: %s", local_error->message); +                g_propagate_error (error, local_error); +                return FALSE; +        } + +        local_error = NULL; +        res = g_spawn_async_with_pipes (NULL, +                                        argv, +                                        NULL, +                                        G_SPAWN_DO_NOT_REAP_CHILD, +                                        NULL, +                                        NULL, +                                        &job->priv->child_pid, +                                        NULL, +                                        &standard_output, +                                        &standard_error, +                                        &local_error); + +        g_strfreev (argv); +        if (! res) { +                ck_debug ("Could not start command '%s': %s", +                          job->priv->command, +                          local_error->message); +                g_propagate_error (error, local_error); +                return FALSE; +        } + +        /* output channel */ +        channel = g_io_channel_unix_new (standard_output); +        g_io_channel_set_close_on_unref (channel, TRUE); +        g_io_channel_set_flags (channel, +                                g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK, +                                NULL); +        job->priv->out_watch_id = g_io_add_watch (channel, +                                                  G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, +                                                  (GIOFunc)out_watch, +                                                  job); +        g_io_channel_unref (channel); + +        /* error channel */ +        channel = g_io_channel_unix_new (standard_error); +        g_io_channel_set_close_on_unref (channel, TRUE); +        g_io_channel_set_flags (channel, +                                g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK, +                                NULL); +        job->priv->err_watch_id = g_io_add_watch (channel, +                                                  G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, +                                                  (GIOFunc)error_watch, +                                                  job); +        g_io_channel_unref (channel); + +        return res; +} + +gboolean +ck_job_get_stdout (CkJob *job, +                   char **stdout) +{ +        if (stdout != NULL) { +                *stdout = g_strdup (job->priv->stdout->str); +        } +        return TRUE; +} + +gboolean +ck_job_set_command (CkJob      *job, +                    const char *command) +{ +        g_free (job->priv->command); +        job->priv->command = g_strdup (command); +        return TRUE; +} + +gboolean +ck_job_get_command (CkJob      *job, +                    char      **command) +{ +        if (command != NULL) { +                *command = g_strdup (job->priv->command); +        } + +        return TRUE; +} + +static void +ck_job_class_init (CkJobClass *klass) +{ +        GObjectClass   *object_class = G_OBJECT_CLASS (klass); + +        object_class->finalize = ck_job_finalize; + +        signals [COMPLETED] = +                g_signal_new ("completed", +                              G_TYPE_FROM_CLASS (object_class), +                              G_SIGNAL_RUN_LAST, +                              G_STRUCT_OFFSET (CkJobClass, completed), +                              NULL, +                              NULL, +                              g_cclosure_marshal_VOID__INT, +                              G_TYPE_NONE, +                              1, G_TYPE_INT); + +        g_type_class_add_private (klass, sizeof (CkJobPrivate)); +} + +static void +ck_job_init (CkJob *job) +{ +        job->priv = CK_JOB_GET_PRIVATE (job); + +        job->priv->stderr = g_string_new (NULL); +        job->priv->stdout = g_string_new (NULL); +} + +gboolean +ck_job_cancel (CkJob *job) +{ +        if (job->priv->child_pid > 0) { +                kill (job->priv->child_pid, SIGTERM); +                wait_on_job (job); +                return TRUE; +        } + +        return FALSE; +} + +static void +ck_job_finalize (GObject *object) +{ +        CkJob *job; + +        ck_debug ("Finalizing job"); + +        g_return_if_fail (object != NULL); +        g_return_if_fail (CK_IS_JOB (object)); + +        job = CK_JOB (object); + +        g_return_if_fail (job->priv != NULL); + +        ck_job_cancel (job); + +        if (job->priv->out_watch_id > 0) { +                g_source_remove (job->priv->out_watch_id); +        } +        if (job->priv->err_watch_id > 0) { +                g_source_remove (job->priv->err_watch_id); +        } +        g_free (job->priv->command); +        g_string_free (job->priv->stdout, TRUE); +        g_string_free (job->priv->stderr, TRUE); + +        G_OBJECT_CLASS (ck_job_parent_class)->finalize (object); +} + +CkJob * +ck_job_new (void) +{ +        GObject *object; + +        object = g_object_new (CK_TYPE_JOB, NULL); + +        return CK_JOB (object); +} diff --git a/src/ck-job.h b/src/ck-job.h new file mode 100644 index 0000000..a12a262 --- /dev/null +++ b/src/ck-job.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __CK_JOB_H +#define __CK_JOB_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define CK_TYPE_JOB         (ck_job_get_type ()) +#define CK_JOB(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_JOB, CkJob)) +#define CK_JOB_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_JOB, CkJobClass)) +#define CK_IS_JOB(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_JOB)) +#define CK_IS_JOB_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_JOB)) +#define CK_JOB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_JOB, CkJobClass)) + +typedef struct CkJobPrivate CkJobPrivate; + +typedef struct +{ +        GObject       parent; +        CkJobPrivate *priv; +} CkJob; + +typedef struct +{ +        GObjectClass   parent_class; + +        void          (* completed)            (CkJob *job, +                                                int    status); +} CkJobClass; + +typedef enum +{ +        CK_JOB_ERROR_GENERAL +} CkJobError; + +#define CK_JOB_ERROR ck_job_error_quark () + +GQuark              ck_job_error_quark         (void); +GType               ck_job_get_type            (void); +CkJob             * ck_job_new                 (void); + +gboolean            ck_job_set_command         (CkJob      *job, +                                                const char *command); +gboolean            ck_job_get_command         (CkJob      *job, +                                                char      **command); +gboolean            ck_job_execute             (CkJob      *job, +                                                GError    **error); +gboolean            ck_job_get_stdout          (CkJob      *job, +                                                char      **std_output); +gboolean            ck_job_get_stderr          (CkJob      *job, +                                                char      **std_error); +gboolean            ck_job_cancel              (CkJob      *job); + +G_END_DECLS + +#endif /* __CK_JOB_H */ diff --git a/src/ck-manager.c b/src/ck-manager.c index 080d86e..7ea6315 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -40,6 +40,7 @@  #include "ck-manager-glue.h"  #include "ck-seat.h"  #include "ck-session.h" +#include "ck-job.h"  #include "ck-marshal.h"  #include "ck-debug.h" @@ -75,12 +76,14 @@ struct CkManagerPrivate  typedef struct { +        int         refcount; +        gboolean    cancelled;          uid_t       uid;          pid_t       pid;          char       *service_name;          char       *ssid;          char       *cookie; -        GHashTable *pending_ids; +        GList      *pending_jobs;  } LeaderInfo;  enum { @@ -100,38 +103,65 @@ static gpointer manager_object = NULL;  G_DEFINE_TYPE (CkManager, ck_manager, G_TYPE_OBJECT) -static LeaderInfo * -leader_info_copy (LeaderInfo *info) +static void +remove_pending_job (CkJob *job)  { -        LeaderInfo *new; - -        new = g_new0 (LeaderInfo, 1); +        if (job != NULL) { +                char *command; -        new->uid = info->uid; -        new->pid = info->pid; -        new->service_name = g_strdup (info->service_name); -        new->ssid = g_strdup (info->ssid); -        new->cookie = g_strdup (info->cookie); +                command = NULL; +                ck_job_get_command (job, &command); +                ck_debug ("Removing pending job: %s", command); +                g_free (command); -        if (info->pending_ids != NULL) { -                new->pending_ids = g_hash_table_ref (info->pending_ids); +                ck_job_cancel (job); +                g_object_unref (job);          } - -        return new;  }  static void -leader_info_free (LeaderInfo *info) +_leader_info_free (LeaderInfo *info)  { +        ck_debug ("Freeing leader info: %s", info->ssid); +          g_free (info->ssid); +        info->ssid = NULL;          g_free (info->cookie); +        info->cookie = NULL;          g_free (info->service_name); +        info->service_name = NULL; -        if (info->pending_ids != NULL) { -                g_hash_table_unref (info->pending_ids); +        g_free (info); +} + +static void +leader_info_cancel (LeaderInfo *info) +{ +        if (info->pending_jobs != NULL) { +                g_list_foreach (info->pending_jobs, (GFunc)remove_pending_job, NULL); +                g_list_free (info->pending_jobs); +                info->pending_jobs = NULL;          } -        g_free (info); +        info->cancelled = TRUE; +} + +static void +leader_info_unref (LeaderInfo *info) +{ +        /* Probably should use some kind of atomic op here */ +        info->refcount -= 1; +        if (info->refcount == 0) { +                _leader_info_free (info); +        } +} + +static LeaderInfo * +leader_info_ref (LeaderInfo *info) +{ +        info->refcount += 1; + +        return info;  }  GQuark @@ -366,7 +396,7 @@ manager_set_system_idle_hint (CkManager *manager,                  /* FIXME: can we get a time from the dbus message? */                  g_get_current_time (&manager->priv->system_idle_since_hint); -                ck_debug ("Emitting system-idle-changed"); +                ck_debug ("Emitting system-idle-hint-changed: %d", idle_hint);                  g_signal_emit (manager, signals [SYSTEM_IDLE_HINT_CHANGED], 0, idle_hint);          } @@ -541,15 +571,18 @@ verify_and_open_session_for_leader_info (CkManager             *manager,  }  static void -add_param_int (GPtrArray       *parameters, -               const char      *key, -               int              value) +add_param_int (GPtrArray  *parameters, +               const char *key, +               const char *value)  {          GValue val = { 0, };          GValue param_val = { 0, }; +        int    num; + +        num = atoi (value);          g_value_init (&val, G_TYPE_INT); -        g_value_set_int (&val, value); +        g_value_set_int (&val, num);          g_value_init (¶m_val, CK_TYPE_PARAMETER_STRUCT);          g_value_take_boxed (¶m_val,                              dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT)); @@ -561,15 +594,22 @@ add_param_int (GPtrArray       *parameters,  }  static void -add_param_boolean (GPtrArray       *parameters, -                   const char      *key, -                   gboolean         value) +add_param_boolean (GPtrArray  *parameters, +                   const char *key, +                   const char *value)  { -        GValue val = { 0, }; -        GValue param_val = { 0, }; +        GValue   val = { 0, }; +        GValue   param_val = { 0, }; +        gboolean b; + +        if (value != NULL && strcmp (value, "true") == 0) { +                b = TRUE; +        } else { +                b = FALSE; +        }          g_value_init (&val, G_TYPE_BOOLEAN); -        g_value_set_boolean (&val, value); +        g_value_set_boolean (&val, b);          g_value_init (¶m_val, CK_TYPE_PARAMETER_STRUCT);          g_value_take_boxed (¶m_val,                              dbus_g_type_specialized_construct (CK_TYPE_PARAMETER_STRUCT)); @@ -581,9 +621,9 @@ add_param_boolean (GPtrArray       *parameters,  }  static void -add_param_string (GPtrArray       *parameters, -                  const char      *key, -                  const char      *value) +add_param_string (GPtrArray  *parameters, +                  const char *key, +                  const char *value)  {          GValue val = { 0, };          GValue param_val = { 0, }; @@ -602,23 +642,135 @@ add_param_string (GPtrArray       *parameters,          g_ptr_array_add (parameters, g_value_get_boxed (¶m_val));  } +typedef void (* CkAddParamFunc) (GPtrArray  *arr, +                                 const char *key, +                                 const char *value); + +static struct { +	char          *key; +        CkAddParamFunc func; +} parse_ops[] = { +        { "display-device", add_param_string }, +        { "x11-display",    add_param_string }, +        { "host-name",      add_param_string }, +        { "session-type",   add_param_string }, +        { "is-local",       add_param_boolean }, +        { "user",           add_param_int }, +}; + +static GPtrArray * +parse_output (const char *output) +{ +        GPtrArray *parameters; +        char     **lines; +        int        i; +        int        j; + +        lines = g_strsplit (output, "\n", -1); +        if (lines == NULL) { +                return NULL; +        } + +        parameters = g_ptr_array_sized_new (10); + +        for (i = 0; lines[i] != NULL; i++) { +                char **vals; + +                vals = g_strsplit (lines[i], " = ", 2); +                if (vals == NULL || vals[0] == NULL) { +                        continue; +                } + +                for (j = 0; j < G_N_ELEMENTS (parse_ops); j++) { +                        if (strcmp (vals[0], parse_ops[j].key) == 0) { +                                parse_ops[j].func (parameters, vals[0], vals[1]); +                                break; +                        } +                } +                g_strfreev (vals); +        } + +        return parameters; +} + +typedef struct { +        CkManager             *manager; +        LeaderInfo            *leader_info; +        DBusGMethodInvocation *context; +} JobData; + +static void +job_data_free (JobData *data) +{ +        leader_info_unref (data->leader_info); +        g_free (data); +} + +static void +job_completed (CkJob     *job, +               int        status, +               JobData   *data) +{ +        ck_debug ("Job status: %d", status); +        if (status == 0) { +                char      *output; +                GPtrArray *parameters; + +                output = NULL; +                ck_job_get_stdout (job, &output); +                ck_debug ("Job output: %s", output); + +                parameters = parse_output (output); +                g_free (output); + +                verify_and_open_session_for_leader_info (data->manager, +                                                         data->leader_info, +                                                         parameters, +                                                         data->context); + +                g_ptr_array_free (parameters, TRUE); + +        } + +        /* remove job from queue */ +        data->leader_info->pending_jobs = g_list_remove (data->leader_info->pending_jobs, job); + +        g_signal_handlers_disconnect_by_func (job, job_completed, data); +        g_object_unref (job); +} +  static void  generate_session_for_leader_info (CkManager             *manager,                                    LeaderInfo            *leader_info,                                    DBusGMethodInvocation *context)  { -        GPtrArray   *parameters;          GError      *local_error; -        proc_stat_t *stat; -        char        *cmd; -        char        *x11_display; -        char        *tty; +        char        *command;          gboolean     res; - -        /* FIXME: callout to a helper tool to generate all parameters */ +        CkJob       *job; +        JobData     *data; + +        command = g_strdup_printf ("%s --uid %u --pid %u", +                                   LIBEXECDIR "/ck-collect-session-info", +                                   leader_info->uid, +                                   leader_info->pid); +        job = ck_job_new (); +        ck_job_set_command (job, command); +        g_free (command); + +        data = g_new0 (JobData, 1); +        data->manager = manager; +        data->leader_info = leader_info_ref (leader_info); +        data->context = context; +        g_signal_connect_data (job, +                               "completed", +                               G_CALLBACK (job_completed), +                               data, +                               (GClosureNotify)job_data_free, +                               0);          local_error = NULL; -        res = proc_stat_new_for_pid (leader_info->pid, &stat, &local_error); +        res = ck_job_execute (job, &local_error);          if (! res) {                  GError *error;                  error = g_error_new (CK_MANAGER_ERROR, @@ -632,33 +784,13 @@ generate_session_for_leader_info (CkManager             *manager,                          g_error_free (local_error);                  } +                g_object_unref (job); +                  return;          } -        tty = proc_stat_get_tty (stat); -        cmd = proc_stat_get_cmd (stat); -        x11_display = NULL; -        proc_stat_free (stat); - -        parameters = g_ptr_array_sized_new (10); -        /* FIXME: What should this be? */ -        add_param_boolean (parameters, "is-local", TRUE); -        add_param_int (parameters, "user", leader_info->uid); -        add_param_string (parameters, "x11-display", x11_display); -        add_param_string (parameters, "display-device", tty); -        /* FIXME: this isn't really a reliable value to use */ -        add_param_string (parameters, "session-type", cmd); - -        g_free (x11_display); -        g_free (cmd); -        g_free (tty); - -        verify_and_open_session_for_leader_info (manager, -                                                 leader_info, -                                                 parameters, -                                                 context); - -	g_ptr_array_free (parameters, TRUE); +        /* Add job to queue */ +        leader_info->pending_jobs = g_list_prepend (leader_info->pending_jobs, job);  }  static gboolean @@ -701,7 +833,9 @@ create_session_for_sender (CkManager             *manager,          leader_info->cookie = g_strdup (cookie);          /* need to store the leader info first so the pending request can be revoked */ -        g_hash_table_insert (manager->priv->leaders, g_strdup (leader_info->cookie), leader_info); +        g_hash_table_insert (manager->priv->leaders, +                             g_strdup (leader_info->cookie), +                             leader_info_ref (leader_info));          if (parameters == NULL) {                  generate_session_for_leader_info (manager, @@ -967,13 +1101,6 @@ ck_manager_open_session_with_parameters (CkManager             *manager,  }  static gboolean -cancel_pending_actions_for_cookie (CkManager  *manager, -                                   const char *cookie) -{ -        return TRUE; -} - -static gboolean  remove_session_for_cookie (CkManager  *manager,                             const char *cookie,                             GError    **error) @@ -1150,9 +1277,8 @@ remove_leader_for_connection (const char       *cookie,          g_assert (data->service_name != NULL);          if (strcmp (info->service_name, data->service_name) == 0) { -                cancel_pending_actions_for_cookie (data->manager, cookie);                  remove_session_for_cookie (data->manager, cookie, NULL); - +                leader_info_cancel (info);                  return TRUE;          } @@ -1371,7 +1497,7 @@ ck_manager_init (CkManager *manager)          manager->priv->leaders = g_hash_table_new_full (g_str_hash,                                                          g_str_equal,                                                          g_free, -                                                        (GDestroyNotify) leader_info_free); +                                                        (GDestroyNotify) leader_info_unref);          create_seats (manager);  }  | 
