summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2010-09-20 00:45:16 +0200
committerLennart Poettering <lennart@poettering.net>2010-09-20 01:16:32 +0200
commit24dc214f55e7c7c17d888d0ccf94cd3625767462 (patch)
tree2f1eef8ea027530407935324cb4e7afb71fdb8f9
parent2d16bc565247b8d8653e7eb4a7a6b0d940142bb6 (diff)
linux: Check for VT_WAITEVENT ioctl during runtime
Since 2782cc8d4950effbc4407455e72bd4750cef6e11 ConsoleKit fails, if it has been compiled on a linux kernel >= 2.6.32 but is run with an older kernel. Check for VT_WAITEVENT ioctl during runtime and fallback to the old behaviour of creating a thread for every possible vt.
-rw-r--r--src/ck-vt-monitor.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/src/ck-vt-monitor.c b/src/ck-vt-monitor.c
index 369c63e..9310341 100644
--- a/src/ck-vt-monitor.c
+++ b/src/ck-vt-monitor.c
@@ -27,6 +27,7 @@
#include <string.h>
#include <errno.h>
#include <signal.h>
+#include <sys/ioctl.h>
#include <glib.h>
#include <glib/gi18n.h>
@@ -311,6 +312,34 @@ schedule_process_queue (CkVtMonitor *vt_monitor)
G_UNLOCK (schedule_lock);
}
+#ifdef VT_WAITEVENT
+static gboolean
+vt_waitevent_supported (int fd)
+{
+ static int supported = -1;
+ int res;
+
+ if (supported >= 0)
+ return supported;
+
+ res = ioctl(fd, VT_WAITEVENT, NULL);
+
+ if (res == ERROR) {
+ if (errno == EINVAL) {
+ g_debug ("VT_WAITEVENT not supported on this system");
+ supported = FALSE;
+ return FALSE;
+ } else if (errno == EFAULT) {
+ g_debug ("VT_WAITEVENT supported on this system");
+ supported = TRUE;
+ return TRUE;
+ }
+ }
+ g_debug ("Unexpected result for VT_WAITEVENT check, returning FALSE");
+ return FALSE;
+}
+#endif
+
static void *
vt_thread_start (ThreadData *data)
{
@@ -322,6 +351,9 @@ vt_thread_start (ThreadData *data)
num = data->num;
#ifdef VT_WAITEVENT
+ if (!vt_waitevent_supported(vt_monitor->priv->vfd))
+ goto no_waitevent;
+
for (;;) {
res = ck_wait_for_console_switch (vt_monitor->priv->vfd, &num);
if (! res) {
@@ -340,7 +372,10 @@ vt_thread_start (ThreadData *data)
schedule_process_queue (vt_monitor);
}
}
-#else
+ goto out;
+#endif
+
+no_waitevent:
res = ck_wait_for_active_console_num (vt_monitor->priv->vfd, num);
if (! res) {
/* FIXME: what do we do if it fails? */
@@ -357,8 +392,8 @@ vt_thread_start (ThreadData *data)
/* schedule processing of queue */
schedule_process_queue (vt_monitor);
}
-#endif
+out:
G_LOCK (hash_lock);
if (vt_monitor->priv->vt_thread_hash != NULL) {
g_hash_table_remove (vt_monitor->priv->vt_thread_hash, GUINT_TO_POINTER (num));
@@ -418,19 +453,24 @@ vt_add_watches (CkVtMonitor *vt_monitor)
sigaction (SIGPOLL, &act, NULL);
ioctl (vt_monitor->priv->vfd, I_SETSIG, S_MSG);
-#elif defined (VT_WAITEVENT)
+#else
+ guint max_consoles;
+ int i;
+ gint32 current_num;
gpointer id;
+#if defined (VT_WAITEVENT)
+ if (!vt_waitevent_supported(vt_monitor->priv->vfd))
+ goto no_waitevent;
+
G_LOCK (hash_lock);
id = GINT_TO_POINTER (1);
if (g_hash_table_lookup (vt_monitor->priv->vt_thread_hash, id) == NULL)
vt_add_watch_unlocked (vt_monitor, 1);
- G_UNLOCK (hash_lock);
-#else
- guint max_consoles;
- int i;
- gint32 current_num;
+ goto out;
+#endif
+no_waitevent:
G_LOCK (hash_lock);
current_num = vt_monitor->priv->active_num;
@@ -442,7 +482,6 @@ vt_add_watches (CkVtMonitor *vt_monitor)
}
for (i = 1; i < max_consoles; i++) {
- gpointer id;
/* don't wait on the active vc */
if (i == current_num) {
@@ -457,6 +496,7 @@ vt_add_watches (CkVtMonitor *vt_monitor)
}
}
+out:
G_UNLOCK (hash_lock);
#endif
}