- closes #134
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gtk-helpers/secrets.c | 36 +++++++++++++++++++++++++++++-------
1 file changed, 29 insertions(+), 7 deletions(-)
diff --git a/src/gtk-helpers/secrets.c b/src/gtk-helpers/secrets.c
index 72af67d..37c0a03 100644
--- a/src/gtk-helpers/secrets.c
+++ b/src/gtk-helpers/secrets.c
@@ -388,6 +388,7 @@ struct secrets_loop_env
{
GMainContext* gcontext;
GMainLoop *gloop;
+ GSource *timeout_source;
GtkWidget *timeout_dialog;
};
@@ -405,6 +406,18 @@ struct prompt_call_back_args
struct secrets_loop_env *env;
};
+static void nuke_timeout_source(GSource *source)
+{
+ if (NULL == source)
+ return;
+
+ if (!g_source_is_destroyed(source))
+ /* detach it from GMainContext if it is attached */
+ g_source_destroy(source);
+
+ g_source_unref(source);
+}
+
static void prompt_quit_loop(struct secrets_loop_env *env)
{
if (NULL != env->timeout_dialog)
@@ -413,6 +426,9 @@ static void prompt_quit_loop(struct secrets_loop_env *env)
env->timeout_dialog = NULL;
}
+ nuke_timeout_source(env->timeout_source);
+ env->timeout_source = NULL;
+
if (g_main_loop_is_running(env->gloop))
g_main_loop_quit(env->gloop);
}
@@ -552,15 +568,20 @@ static gboolean prompt_timeout_cb(gpointer user_data)
*/
static void prompt_timeout_start(struct secrets_loop_env *env)
{
- GSource *timeout_source= g_timeout_source_new_seconds(PROMPT_TIMEOUT_SECONDS);
+ /* Clean up the old timeout source, it can't be attached to the context again.
+ *
http://developer.gnome.org/glib/2.34/glib-The-Main-Event-Loop.html#g-sour...
+ *
+ * The old timeout source was destroyed by GMainContext because source's
+ * callback (prompt_timeout_cb) returns FALSE. The callback must return
+ * FALSE because neither the expiration time of timeout source can be reset
+ * nor timeout can be suspended.
+ */
+ nuke_timeout_source(env->timeout_source);
- g_source_set_callback(timeout_source, prompt_timeout_cb, /*callback arg*/env, /*arg
destroyer*/NULL);
- g_source_attach(timeout_source, env->gcontext);
+ env->timeout_source= g_timeout_source_new_seconds(PROMPT_TIMEOUT_SECONDS);
- /* remove local reference, the source will be destroyed by the GMainContext
- * over taken from glib2/gmain.c: g_timeout_add_full()
- */
- g_source_unref(timeout_source);
+ g_source_set_callback(env->timeout_source, prompt_timeout_cb, /*callback arg*/env,
/*arg destroyer*/NULL);
+ g_source_attach(env->timeout_source, env->gcontext);
}
/*
@@ -596,6 +617,7 @@ static GVariant *secrets_prompt(const char *prompt_path,
struct secrets_loop_env env = {
.gcontext=context,
.gloop=g_main_loop_new(context, FALSE),
+ .timeout_source=NULL,
.timeout_dialog=NULL,
};
--
1.8.1.2