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);
}
|