Xig

Merge lp:~smspillaz/xig/xig.clean-up-after-clients into lp:xig

Proposed by Sam Spilsbury
Status: Work in progress
Proposed branch: lp:~smspillaz/xig/xig.clean-up-after-clients
Merge into: lp:xig
Prerequisite: lp:~smspillaz/xig/xig.real-get-property-reply-message-length
Diff against target: 349 lines (+174/-58)
4 files modified
src/xig-remote-client-private.h (+5/-0)
src/xig-remote-client.c (+24/-1)
src/xig-server.c (+67/-19)
src/xig-window.c (+78/-38)
To merge this branch: bzr merge lp:~smspillaz/xig/xig.clean-up-after-clients
Reviewer Review Type Date Requested Status
Robert Ancell Needs Fixing
Review via email: mp+89533@code.launchpad.net

Description of the change

Remove window id's left behind by clients due to buggy X extension libraries or by SIGKILL.

Remove stale selections

To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

This patch seems a little back to front... I'd expect the client to maintain the list of resources rather than have the server call back to it. I need to think this one over a bit more (though the concept is 100% correct of course).

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

The server already maintains a list of resources, so when the client goes away we need to figure out which resources the client owns and get rid of them on the server side lists too.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

From me via IRC:

"What you really should do is the server should connected to the destroyed signal for the resources and remove them that way
 so you're explicitly destroying the references from both sides, but the server should be implicitly destroying them
 (or the other way around). The patch has both the server and client responsible which is dangerous if one of them gets out of sync.

So there's two ways we can do this - the client destroys itself, and the server detects that and destroys all its resources, or the client destroys all its resources then itself, and the server doesn't care"

and Sam said "So I think the best way to handle this is to have a XigClientResource which XigSelection and XigDrawable inherit"

Which is correct.

review: Needs Fixing

Unmerged revisions

255. By Sam Spilsbury

Clean up after clients - remove stale resource id's and selections. Also
handle the edge case where clients die and leave stuff behind.

254. By Sam Spilsbury

Write message length according to format, not actual length as that's too much

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/xig-remote-client-private.h'
--- src/xig-remote-client-private.h 2011-12-01 23:46:20 +0000
+++ src/xig-remote-client-private.h 2012-01-21 11:59:25 +0000
@@ -23,4 +23,9 @@
2323
24void _xig_remote_client_circulate_request (XigRemoteClient *client, XigWindow *window, XigCirculatePlace place);24void _xig_remote_client_circulate_request (XigRemoteClient *client, XigWindow *window, XigCirculatePlace place);
2525
26GList * _xig_remote_client_get_owned_drawables (XigRemoteClient *client);
27
28void _xig_remote_client_add_drawable (XigRemoteClient *client, XigDrawable *drawable);
29void _xig_remote_client_remove_drawable (XigRemoteClient *client, XigDrawable *drawable);
30
26#endif /* _XIG_REMOTE_CLIENT_PRIVATE_H_ */31#endif /* _XIG_REMOTE_CLIENT_PRIVATE_H_ */
2732
=== modified file 'src/xig-remote-client.c'
--- src/xig-remote-client.c 2012-01-10 16:45:57 +0000
+++ src/xig-remote-client.c 2012-01-21 11:59:25 +0000
@@ -47,6 +47,9 @@
4747
48 /* Event masks */48 /* Event masks */
49 GHashTable *window_events;49 GHashTable *window_events;
50
51 /* Owned windows */
52 GHashTable *owned_drawables;
50};53};
5154
52enum55enum
@@ -287,6 +290,24 @@
287 xig_codec_feed_circulate_request (XIG_CODEC (client), &message);290 xig_codec_feed_circulate_request (XIG_CODEC (client), &message);
288}291}
289292
293GList *
294_xig_remote_client_get_owned_drawables (XigRemoteClient *client)
295{
296 return g_hash_table_get_keys (client->priv->owned_drawables);
297}
298
299void
300_xig_remote_client_add_drawable (XigRemoteClient *client, XigDrawable *drawable)
301{
302 g_hash_table_insert (client->priv->owned_drawables, GINT_TO_POINTER (xig_drawable_get_id (drawable)), g_object_ref (drawable));
303}
304
305void
306_xig_remote_client_remove_drawable (XigRemoteClient *client, XigDrawable *drawable)
307{
308 g_hash_table_remove (client->priv->owned_drawables, GINT_TO_POINTER (xig_drawable_get_id (drawable)));
309}
310
290static void311static void
291circulate_notify_cb (XigWindow *window, XigRemoteClient *client)312circulate_notify_cb (XigWindow *window, XigRemoteClient *client)
292{313{
@@ -412,7 +433,7 @@
412 if (n_read < 0)433 if (n_read < 0)
413 g_warning ("Error reading from socket: %s", strerror (errno));434 g_warning ("Error reading from socket: %s", strerror (errno));
414 else if (n_read == 0)435 else if (n_read == 0)
415 { 436 {
416 g_signal_emit (client, signals[DISCONNECTED], 0);437 g_signal_emit (client, signals[DISCONNECTED], 0);
417 return FALSE;438 return FALSE;
418 }439 }
@@ -1574,6 +1595,7 @@
15741595
1575 reply.sequence_number = message->sequence_number;1596 reply.sequence_number = message->sequence_number;
1576 focus = xig_server_get_input_focus (client->priv->server, &reply.revert_to);1597 focus = xig_server_get_input_focus (client->priv->server, &reply.revert_to);
1598
1577 reply.focus = focus ? xig_window_get_id (focus) : XIG_WINDOW_ID_NONE;1599 reply.focus = focus ? xig_window_get_id (focus) : XIG_WINDOW_ID_NONE;
15781600
1579 xig_codec_feed_get_input_focus_reply (XIG_CODEC (codec), &reply);1601 xig_codec_feed_get_input_focus_reply (XIG_CODEC (codec), &reply);
@@ -2582,6 +2604,7 @@
2582 client->priv->server = server;2604 client->priv->server = server;
2583 client->priv->socket = g_object_ref (socket);2605 client->priv->socket = g_object_ref (socket);
2584 client->priv->channel = g_io_channel_unix_new (g_socket_get_fd (socket));2606 client->priv->channel = g_io_channel_unix_new (g_socket_get_fd (socket));
2607 client->priv->owned_drawables = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
2585 g_io_add_watch (client->priv->channel, G_IO_IN, socket_data_cb, client);2608 g_io_add_watch (client->priv->channel, G_IO_IN, socket_data_cb, client);
25862609
2587 return client;2610 return client;
25882611
=== modified file 'src/xig-server.c'
--- src/xig-server.c 2011-12-02 10:34:45 +0000
+++ src/xig-server.c 2012-01-21 11:59:25 +0000
@@ -150,12 +150,78 @@
150 server->priv->listen_tcp = listen_tcp;150 server->priv->listen_tcp = listen_tcp;
151}151}
152152
153static gboolean
154_xig_server_hash_table_remove_selection_for_window (gpointer key,
155 gpointer owner,
156 gpointer user_data)
157{
158 return owner == user_data ? TRUE : FALSE;
159}
160
161void
162_xig_server_remove_window (XigServer *server, XigWindow *window)
163{
164 g_hash_table_remove (server->priv->drawables, GINT_TO_POINTER (xig_drawable_get_id (XIG_DRAWABLE (window))));
165
166 /* Remove any selection owners too */
167 g_hash_table_foreach_remove (server->priv->selection_owners, _xig_server_hash_table_remove_selection_for_window, (gpointer) window);
168
169 /* Unset the focus window (revert to root window */
170 if (window == server->priv->focus_window)
171 server->priv->focus_window = NULL;
172}
173
174void
175_xig_server_add_window (XigServer *server, XigWindow *window)
176{
177 g_hash_table_insert (server->priv->drawables, GINT_TO_POINTER (xig_drawable_get_id (XIG_DRAWABLE (window))), g_object_ref (window));
178}
179
180void
181_xig_server_add_pixmap (XigServer *server, XigPixmap *pixmap)
182{
183 g_hash_table_insert (server->priv->drawables, GINT_TO_POINTER (xig_drawable_get_id (XIG_DRAWABLE (pixmap))), g_object_ref (pixmap));
184}
185
186void
187_xig_server_remove_pixmap (XigServer *server, XigPixmap *pixmap)
188{
189 g_hash_table_remove (server->priv->drawables, GINT_TO_POINTER (xig_drawable_get_id (XIG_DRAWABLE (pixmap))));
190}
191
192
153static void193static void
154xig_remote_client_disconnected_cb (XigRemoteClient *client, XigServer *server)194xig_remote_client_disconnected_cb (XigRemoteClient *client, XigServer *server)
155{195{
156 g_signal_handlers_disconnect_matched (client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, server);196 g_signal_handlers_disconnect_matched (client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, server);
157 server->priv->clients = g_list_remove (server->priv->clients, client);197 server->priv->clients = g_list_remove (server->priv->clients, client);
158 g_signal_emit (server, signals[CLIENT_DISCONNECTED], 0, client);198 g_signal_emit (server, signals[CLIENT_DISCONNECTED], 0, client);
199
200 GList *list = _xig_remote_client_get_owned_drawables (client);
201 GList *orig = list;
202
203 while (list)
204 {
205 gint id = GPOINTER_TO_INT (list->data);
206 XigDrawable *drawable = g_hash_table_lookup (server->priv->drawables, GINT_TO_POINTER (id));
207
208 if (XIG_IS_WINDOW (drawable))
209 {
210 XigWindow *window = XIG_WINDOW (drawable);
211
212 _xig_server_remove_window (server, window);
213 }
214 else if (XIG_IS_PIXMAP (drawable))
215 {
216 XigPixmap *pixmap = XIG_PIXMAP (drawable);
217
218 _xig_server_remove_pixmap (server, pixmap);
219 }
220 list = g_list_next (list);
221 }
222
223 g_list_free (orig);
224
159 g_object_unref (client);225 g_object_unref (client);
160}226}
161227
@@ -257,12 +323,6 @@
257}323}
258324
259void325void
260_xig_server_add_window (XigServer *server, XigWindow *window)
261{
262 g_hash_table_insert (server->priv->drawables, GINT_TO_POINTER (xig_drawable_get_id (XIG_DRAWABLE (window))), g_object_ref (window));
263}
264
265void
266_xig_server_set_selection_owner (XigServer *server, const gchar *name, XigWindow *window)326_xig_server_set_selection_owner (XigServer *server, const gchar *name, XigWindow *window)
267{327{
268 g_hash_table_insert (server->priv->selection_owners, g_strdup (name), g_object_ref (window)); 328 g_hash_table_insert (server->priv->selection_owners, g_strdup (name), g_object_ref (window));
@@ -274,18 +334,6 @@
274 return g_hash_table_lookup (server->priv->selection_owners, name);334 return g_hash_table_lookup (server->priv->selection_owners, name);
275}335}
276336
277void
278_xig_server_add_pixmap (XigServer *server, XigPixmap *pixmap)
279{
280 g_hash_table_insert (server->priv->drawables, GINT_TO_POINTER (xig_drawable_get_id (XIG_DRAWABLE (pixmap))), g_object_ref (pixmap));
281}
282
283void
284_xig_server_remove_pixmap (XigServer *server, XigPixmap *pixmap)
285{
286 g_hash_table_remove (server->priv->drawables, GINT_TO_POINTER (xig_drawable_get_id (XIG_DRAWABLE (pixmap))));
287}
288
289XigDrawable *337XigDrawable *
290xig_server_get_drawable (XigServer *server, guint32 drawable)338xig_server_get_drawable (XigServer *server, guint32 drawable)
291{339{
@@ -346,7 +394,7 @@
346void394void
347xig_server_set_input_focus (XigServer *server, XigWindow *window, guint8 revert_to)395xig_server_set_input_focus (XigServer *server, XigWindow *window, guint8 revert_to)
348{396{
349 server->priv->focus_window = g_object_ref (window);397 server->priv->focus_window = window;
350 // FIXME: Catch delete event398 // FIXME: Catch delete event
351 server->priv->focus_revert_to = revert_to;399 server->priv->focus_revert_to = revert_to;
352}400}
353401
=== modified file 'src/xig-window.c'
--- src/xig-window.c 2012-01-10 17:14:41 +0000
+++ src/xig-window.c 2012-01-21 11:59:25 +0000
@@ -76,6 +76,76 @@
76};76};
77static guint signals[LAST_SIGNAL] = { 0 };77static guint signals[LAST_SIGNAL] = { 0 };
7878
79static void
80destroy_recursive (XigWindow *window)
81{
82 GList *link;
83
84 /* Destroy all children first */
85 for (link = window->priv->children; link; link = link->next)
86 {
87 XigWindow *w = link->data;
88 destroy_recursive (w);
89 }
90
91 g_signal_emit (window, signals[DESTROY_NOTIFY], 0);
92 g_signal_emit (window->priv->parent, signals[CHILD_DESTROY_NOTIFY], 0, window);
93
94 g_object_unref (window);
95}
96
97void
98xig_window_destroy (XigWindow *window)
99{
100 window->priv->parent->priv->children = g_list_remove (window->priv->parent->priv->children, window);
101 destroy_recursive (window);
102}
103
104void
105xig_window_destroy_subwindows (XigWindow *window)
106{
107 GList *link;
108 for (link = window->priv->children; link; link = link->next)
109 {
110 XigWindow *w = link->data;
111 destroy_recursive (w);
112 }
113 g_list_free (window->priv->children);
114 window->priv->children = NULL;
115}
116
117/* When clients disconnect, they are meant to (implicitly, through xcb)
118 * remove any resources that they held. When a client dies, it can't do that
119 * so clean up after it */
120static void
121xig_window_client_disconnected_cb (XigServer *server, XigRemoteClient *client, XigWindow *window)
122{
123 GList *list = _xig_remote_client_get_owned_drawables (client);
124 GList *orig = list;
125
126 while (list)
127 {
128 gint id = GPOINTER_TO_INT (list->data);
129
130 GList *child = window->priv->children;
131
132 while (child)
133 {
134 if (xig_window_get_id (XIG_WINDOW (child->data)) == id)
135 {
136 xig_window_destroy (XIG_WINDOW (child->data));
137 break;
138 }
139
140 child = g_list_next (child);
141 }
142
143 list = g_list_next (list);
144 }
145
146 g_list_free (orig);
147}
148
79XigWindow *149XigWindow *
80_xig_window_new (XigServer *server, XigRemoteClient *client, guint32 wid, XigWindow *parent, XigWindowClassType class, gint16 x, gint16 y, guint16 width, guint16 height, guint16 border_width, XigVisual *visual)150_xig_window_new (XigServer *server, XigRemoteClient *client, guint32 wid, XigWindow *parent, XigWindowClassType class, gint16 x, gint16 y, guint16 width, guint16 height, guint16 border_width, XigVisual *visual)
81{151{
@@ -97,6 +167,10 @@
97 window->priv->border_width = border_width;167 window->priv->border_width = border_width;
98 window->priv->visual = g_object_ref (visual);168 window->priv->visual = g_object_ref (visual);
99169
170 if (client)
171 _xig_remote_client_add_drawable (client, XIG_DRAWABLE (window));
172 g_signal_connect (server, "client-disconnected", G_CALLBACK (xig_window_client_disconnected_cb), window);
173
100 if (parent)174 if (parent)
101 g_signal_emit (parent, signals[CREATE_NOTIFY], 0, window);175 g_signal_emit (parent, signals[CREATE_NOTIFY], 0, window);
102176
@@ -695,44 +769,6 @@
695}769}
696770
697static void771static void
698destroy_recursive (XigWindow *window)
699{
700 GList *link;
701
702 /* Destroy all children first */
703 for (link = window->priv->children; link; link = link->next)
704 {
705 XigWindow *w = link->data;
706 destroy_recursive (w);
707 }
708
709 g_signal_emit (window, signals[DESTROY_NOTIFY], 0);
710 g_signal_emit (window->priv->parent, signals[CHILD_DESTROY_NOTIFY], 0, window);
711
712 g_object_unref (window);
713}
714
715void
716xig_window_destroy (XigWindow *window)
717{
718 window->priv->parent->priv->children = g_list_remove (window->priv->parent->priv->children, window);
719 destroy_recursive (window);
720}
721
722void
723xig_window_destroy_subwindows (XigWindow *window)
724{
725 GList *link;
726 for (link = window->priv->children; link; link = link->next)
727 {
728 XigWindow *w = link->data;
729 destroy_recursive (w);
730 }
731 g_list_free (window->priv->children);
732 window->priv->children = NULL;
733}
734
735static void
736xig_window_init (XigWindow *window)772xig_window_init (XigWindow *window)
737{773{
738 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, xig_window_get_type (), XigWindowPrivate);774 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, xig_window_get_type (), XigWindowPrivate);
@@ -753,6 +789,10 @@
753xig_window_finalize (GObject *object)789xig_window_finalize (GObject *object)
754{790{
755 XigWindow *window = (XigWindow *) object;791 XigWindow *window = (XigWindow *) object;
792
793 if (window->priv->client)
794 _xig_remote_client_remove_drawable (window->priv->client, XIG_DRAWABLE (window));
795
756 if (window->priv->visual)796 if (window->priv->visual)
757 g_object_unref (window->priv->visual);797 g_object_unref (window->priv->visual);
758 if (window->priv->background_pixmap)798 if (window->priv->background_pixmap)

Subscribers

People subscribed via source and target branches