summaryrefslogtreecommitdiffstats
path: root/sysutils/consolekit/files/patch-src_ck-vt-monitor.c
blob: 7db4a46828a8825e57982e548281921c2ae5e0ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
--- src/ck-vt-monitor.c.orig    2008-01-23 09:30:44.000000000 -0500
+++ src/ck-vt-monitor.c 2008-01-23 15:29:52.000000000 -0500
@@ -54,6 +54,9 @@ struct CkVtMonitorPrivate
 
         GAsyncQueue     *event_queue;
         guint            process_queue_id;
+
+        GAsyncQueue     *restart_queue;
+        guint            restart_queue_id;
 };
 
 enum {
@@ -72,6 +75,7 @@ static void     ck_vt_monitor_init      
 static void     ck_vt_monitor_finalize    (GObject          *object);
 
 static void     vt_add_watches            (CkVtMonitor      *vt_monitor);
+static void     vt_add_watch_unlocked     (CkVtMonitor      *vt_monitor, gint32 num);
 
 G_DEFINE_TYPE (CkVtMonitor, ck_vt_monitor, G_TYPE_OBJECT)
 
@@ -254,6 +258,56 @@ process_queue (CkVtMonitor *vt_monitor)
         return FALSE;
 }
 
+static gboolean
+process_restart_queue (CkVtMonitor *vt_monitor)
+{
+        int        i;
+        int        queue_length;
+        EventData *data;
+        EventData *d;
+
+        g_async_queue_lock (vt_monitor->priv->restart_queue);
+
+        g_debug ("Processing VT restart queue");
+
+        queue_length = g_async_queue_length_unlocked (vt_monitor->priv->restart_queue);
+        data = NULL;
+
+        G_LOCK (hash_lock);
+
+        /* compress events in the queue */
+        for (i = 0; i < queue_length; i++) {
+                d = g_async_queue_try_pop_unlocked (vt_monitor->priv->restart_queue);
+                if (d == NULL) {
+                        continue;
+
+                }
+
+                if (data != NULL) {
+                        g_debug ("Compressing queue; skipping restart for VT %d", data->num);
+                        event_data_free (data);
+                }
+
+                data = d;
+        }
+
+        if (data != NULL) {
+                vt_add_watch_unlocked (vt_monitor, data->num);
+                event_data_free (data);
+        }
+
+        G_UNLOCK (hash_lock);
+
+        G_LOCK (schedule_lock);
+        vt_monitor->priv->restart_queue_id = 0;
+        G_UNLOCK (schedule_lock);
+
+        g_async_queue_unlock (vt_monitor->priv->restart_queue);
+
+        return FALSE;
+}
+
+
 static void
 schedule_process_queue (CkVtMonitor *vt_monitor)
 {
@@ -264,6 +318,16 @@ schedule_process_queue (CkVtMonitor *vt_
         G_UNLOCK (schedule_lock);
 }
 
+static void
+schedule_process_restart_queue (CkVtMonitor *vt_monitor)
+{
+        G_LOCK (schedule_lock);
+        if (vt_monitor->priv->restart_queue_id == 0) {
+                vt_monitor->priv->restart_queue_id = g_idle_add ((GSourceFunc)process_restart_queue, vt_monitor);
+        }
+        G_UNLOCK (schedule_lock);
+}
+
 static void *
 vt_thread_start (ThreadData *data)
 {
@@ -277,7 +341,15 @@ vt_thread_start (ThreadData *data)
 
         res = ck_wait_for_active_console_num (vt_monitor->priv->vfd, num);
         if (! res) {
-                /* FIXME: what do we do if it fails? */
+                EventData *event;
+
+                event = g_new0 (EventData, 1);
+                event->num = num;
+                g_debug ("Failed to wait for active console %d: %s", num, g_strerror (errno));
+
+                g_async_queue_push (vt_monitor->priv->restart_queue, event);
+
+                schedule_process_restart_queue (vt_monitor);
         } else {
                 EventData *event;
 
@@ -414,6 +486,7 @@ ck_vt_monitor_init (CkVtMonitor *vt_moni
 
                 vt_monitor->priv->active_num = active;
                 vt_monitor->priv->event_queue = g_async_queue_new ();
+                vt_monitor->priv->restart_queue = g_async_queue_new ();
                 vt_monitor->priv->vt_thread_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
 
                 vt_add_watches (vt_monitor);
@@ -440,6 +513,10 @@ ck_vt_monitor_finalize (GObject *object)
                 g_async_queue_unref (vt_monitor->priv->event_queue);
         }
 
+        if (vt_monitor->priv->restart_queue != NULL) {
+                g_async_queue_unref (vt_monitor->priv->restart_queue);
+        }
+
         if (vt_monitor->priv->vt_thread_hash != NULL) {
                 g_hash_table_destroy (vt_monitor->priv->vt_thread_hash);
         }