Commit 98f8a224 authored by Chris Coulson's avatar Chris Coulson Committed by William Jon McCann

Work around x errors by asking dialog to die on cancel

Basically, what is happening is that gnome-screensaver-dialog exits after the
5th failed attempt at unlocking the screen, but before the shake animation
finishes. If the timing is slightly unlucky, this results in gnome-screensaver
accessing X resources that have already been destroyed (I ran it through
xtrace, and that showed this happening)

My patch fixes this by making gnome-screensaver-dialog request to
gnome-screensaver that it be terminated after the 5th failed attempt (rather
than exitting straight away, although there is a fallback timeout too).
gnome-screensaver then terminates the dialog after it is finished with the
shake animation, to avoid the race condition that is currently making it crash.
parent 0f4f0934
......@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <glib/gi18n.h>
#include <gdk/gdkx.h>
......@@ -325,6 +326,21 @@ response_cb (GSLockPlug *plug,
}
}
static gboolean
response_request_quit (void)
{
printf ("REQUEST QUIT\n");
fflush (stdout);
return FALSE;
}
static gboolean
quit_timeout_cb (gpointer data)
{
gtk_main_quit ();
return FALSE;
}
static gboolean
auth_check_idle (GSLockPlug *plug)
{
......@@ -347,7 +363,11 @@ auth_check_idle (GSLockPlug *plug)
} else {
gs_debug ("Authentication failed, quitting (max failures)");
again = FALSE;
gtk_main_quit ();
/* Don't quit immediately, but rather request that gnome-screensaver
* terminates us after it has finished the dialog shake. Time out
* after 5 seconds and quit anyway if this doesn't happen though */
g_idle_add ((GSourceFunc)response_request_quit, NULL);
g_timeout_add (5000, (GSourceFunc)quit_timeout_cb, NULL);
}
}
......
......@@ -91,6 +91,8 @@ struct GSWindowPrivate
gint lock_pid;
gint lock_watch_id;
gint dialog_response;
gboolean dialog_quit_requested;
gboolean dialog_shake_in_progress;
gint keyboard_pid;
gint keyboard_watch_id;
......@@ -1383,6 +1385,16 @@ gs_window_dialog_finish (GSWindow *window)
remove_key_events (window);
}
static void
maybe_kill_dialog (GSWindow *window)
{
if (!window->priv->dialog_shake_in_progress
&& window->priv->dialog_quit_requested
&& window->priv->lock_pid > 0) {
kill (window->priv->lock_pid, SIGTERM);
}
}
/* very rudimentary animation for indicating an auth failure */
static void
shake_dialog (GSWindow *window)
......@@ -1391,6 +1403,8 @@ shake_dialog (GSWindow *window)
guint left;
guint right;
window->priv->dialog_shake_in_progress = TRUE;
for (i = 0; i < 9; i++) {
if (i % 2 == 0) {
left = 30;
......@@ -1415,6 +1429,9 @@ shake_dialog (GSWindow *window)
g_usleep (10000);
}
window->priv->dialog_shake_in_progress = FALSE;
maybe_kill_dialog (window);
}
static gboolean
......@@ -1457,6 +1474,10 @@ lock_command_watch (GIOChannel *source,
window->priv->dialog_response = DIALOG_RESPONSE_CANCEL;
}
finished = TRUE;
} else if (strstr (line, "REQUEST QUIT") != NULL) {
gs_debug ("Got request for quit");
window->priv->dialog_quit_requested = TRUE;
maybe_kill_dialog (window);
}
break;
case G_IO_STATUS_EOF:
......@@ -1570,6 +1591,9 @@ popup_dialog_idle (GSWindow *window)
set_invisible_cursor (GTK_WIDGET (window)->window, FALSE);
window->priv->dialog_quit_requested = FALSE;
window->priv->dialog_shake_in_progress = FALSE;
result = spawn_on_window (window,
command->str,
&window->priv->lock_pid,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment