ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/mports/trunk/devel/gvfs/files/patch-common_gvfsdbusutils.c
Revision: 19304
Committed: Tue Jun 2 02:11:44 2015 UTC (8 years, 11 months ago) by laffer1
Content type: text/plain
File size: 13989 byte(s)
Log Message:
gvfs 1.20.3

File Contents

# Content
1 https://bugzilla.gnome.org/show_bug.cgi?id=722411
2
3 --- common/gvfsdbusutils.c.orig 2014-05-25 17:43:08.000000000 +0200
4 +++ common/gvfsdbusutils.c 2014-05-25 17:43:08.000000000 +0200
5 @@ -0,0 +1,538 @@
6 +/* GIO - GLib Input, Output and Streaming Library
7 + *
8 + * Copyright (C) 2006-2007 Red Hat, Inc.
9 + *
10 + * This library is free software; you can redistribute it and/or
11 + * modify it under the terms of the GNU Lesser General Public
12 + * License as published by the Free Software Foundation; either
13 + * version 2 of the License, or (at your option) any later version.
14 + *
15 + * This library is distributed in the hope that it will be useful,
16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 + * Lesser General Public License for more details.
19 + *
20 + * You should have received a copy of the GNU Lesser General
21 + * Public License along with this library; if not, write to the
22 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 + * Boston, MA 02110-1301, USA.
24 + *
25 + * Author: Alexander Larsson <alexl@redhat.com>
26 + */
27 +
28 +#include <config.h>
29 +
30 +#include <stdlib.h>
31 +#include <string.h>
32 +
33 +#include <glib/gi18n-lib.h>
34 +#include <gvfsdbusutils.h>
35 +#include <gio/gio.h>
36 +
37 +static void
38 +_g_dbus_oom (void)
39 +{
40 + g_error ("DBus failed with out of memory error");
41 +}
42 +
43 +/*************************************************************************
44 + * Helper fd source *
45 + ************************************************************************/
46 +
47 +typedef struct
48 +{
49 + GSource source;
50 + GPollFD pollfd;
51 + GCancellable *cancellable;
52 + gulong cancelled_tag;
53 +} FDSource;
54 +
55 +static gboolean
56 +fd_source_prepare (GSource *source,
57 + gint *timeout)
58 +{
59 + FDSource *fd_source = (FDSource *)source;
60 + *timeout = -1;
61 +
62 + return g_cancellable_is_cancelled (fd_source->cancellable);
63 +}
64 +
65 +static gboolean
66 +fd_source_check (GSource *source)
67 +{
68 + FDSource *fd_source = (FDSource *)source;
69 +
70 + return
71 + g_cancellable_is_cancelled (fd_source->cancellable) ||
72 + fd_source->pollfd.revents != 0;
73 +}
74 +
75 +static gboolean
76 +fd_source_dispatch (GSource *source,
77 + GSourceFunc callback,
78 + gpointer user_data)
79 +
80 +{
81 + GFDSourceFunc func = (GFDSourceFunc)callback;
82 + FDSource *fd_source = (FDSource *)source;
83 +
84 + g_assert (func != NULL);
85 +
86 + return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
87 +}
88 +
89 +static void
90 +fd_source_finalize (GSource *source)
91 +{
92 + FDSource *fd_source = (FDSource *)source;
93 +
94 + if (fd_source->cancelled_tag)
95 + g_cancellable_disconnect (fd_source->cancellable,
96 + fd_source->cancelled_tag);
97 +
98 + if (fd_source->cancellable)
99 + g_object_unref (fd_source->cancellable);
100 +}
101 +
102 +static GSourceFuncs fd_source_funcs = {
103 + fd_source_prepare,
104 + fd_source_check,
105 + fd_source_dispatch,
106 + fd_source_finalize
107 +};
108 +
109 +/* Might be called on another thread */
110 +static void
111 +fd_source_cancelled_cb (GCancellable *cancellable,
112 + gpointer data)
113 +{
114 + /* Wake up the mainloop in case we're waiting on async calls with FDSource */
115 + g_main_context_wakeup (NULL);
116 +}
117 +
118 +/* Two __ to avoid conflict with gio version */
119 +GSource *
120 +__g_fd_source_new (int fd,
121 + gushort events,
122 + GCancellable *cancellable)
123 +{
124 + GSource *source;
125 + FDSource *fd_source;
126 +
127 + source = g_source_new (&fd_source_funcs, sizeof (FDSource));
128 + fd_source = (FDSource *)source;
129 +
130 + if (cancellable)
131 + fd_source->cancellable = g_object_ref (cancellable);
132 +
133 + fd_source->pollfd.fd = fd;
134 + fd_source->pollfd.events = events;
135 + g_source_add_poll (source, &fd_source->pollfd);
136 +
137 + if (cancellable)
138 + fd_source->cancelled_tag =
139 + g_cancellable_connect (cancellable,
140 + (GCallback)fd_source_cancelled_cb,
141 + NULL, NULL);
142 +
143 + return source;
144 +}
145 +
146 +/*************************************************************************
147 + * *
148 + * dbus mainloop integration for async ops *
149 + * *
150 + *************************************************************************/
151 +
152 +static gint32 main_integration_data_slot = -1;
153 +static GOnce once_init_main_integration = G_ONCE_INIT;
154 +
155 +/**
156 + * A GSource subclass for dispatching DBusConnection messages.
157 + * We need this on top of the IO handlers, because sometimes
158 + * there are messages to dispatch queued up but no IO pending.
159 + *
160 + * The source is owned by the connection (and the main context
161 + * while that is alive)
162 + */
163 +typedef struct
164 +{
165 + GSource source;
166 +
167 + DBusConnection *connection;
168 + GSList *ios;
169 + GSList *timeouts;
170 +} DBusSource;
171 +
172 +typedef struct
173 +{
174 + DBusSource *dbus_source;
175 + GSource *source;
176 + DBusWatch *watch;
177 +} IOHandler;
178 +
179 +typedef struct
180 +{
181 + DBusSource *dbus_source;
182 + GSource *source;
183 + DBusTimeout *timeout;
184 +} TimeoutHandler;
185 +
186 +static gpointer
187 +main_integration_init (gpointer arg)
188 +{
189 + if (!dbus_connection_allocate_data_slot (&main_integration_data_slot))
190 + g_error ("Unable to allocate data slot");
191 +
192 + return NULL;
193 +}
194 +
195 +static gboolean
196 +dbus_source_prepare (GSource *source,
197 + gint *timeout)
198 +{
199 + DBusConnection *connection = ((DBusSource *)source)->connection;
200 +
201 + *timeout = -1;
202 +
203 + return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
204 +}
205 +
206 +static gboolean
207 +dbus_source_check (GSource *source)
208 +{
209 + return FALSE;
210 +}
211 +
212 +static gboolean
213 +dbus_source_dispatch (GSource *source,
214 + GSourceFunc callback,
215 + gpointer user_data)
216 +{
217 + DBusConnection *connection = ((DBusSource *)source)->connection;
218 +
219 + dbus_connection_ref (connection);
220 +
221 + /* Only dispatch once - we don't want to starve other GSource */
222 + dbus_connection_dispatch (connection);
223 +
224 + dbus_connection_unref (connection);
225 +
226 + return TRUE;
227 +}
228 +
229 +static gboolean
230 +io_handler_dispatch (gpointer data,
231 + GIOCondition condition,
232 + int fd)
233 +{
234 + IOHandler *handler = data;
235 + guint dbus_condition = 0;
236 + DBusConnection *connection;
237 +
238 + connection = handler->dbus_source->connection;
239 +
240 + if (connection)
241 + dbus_connection_ref (connection);
242 +
243 + if (condition & G_IO_IN)
244 + dbus_condition |= DBUS_WATCH_READABLE;
245 + if (condition & G_IO_OUT)
246 + dbus_condition |= DBUS_WATCH_WRITABLE;
247 + if (condition & G_IO_ERR)
248 + dbus_condition |= DBUS_WATCH_ERROR;
249 + if (condition & G_IO_HUP)
250 + dbus_condition |= DBUS_WATCH_HANGUP;
251 +
252 + /* Note that we don't touch the handler after this, because
253 + * dbus may have disabled the watch and thus killed the
254 + * handler.
255 + */
256 + dbus_watch_handle (handler->watch, dbus_condition);
257 + handler = NULL;
258 +
259 + if (connection)
260 + dbus_connection_unref (connection);
261 +
262 + return TRUE;
263 +}
264 +
265 +static void
266 +io_handler_free (IOHandler *handler)
267 +{
268 + DBusSource *dbus_source;
269 +
270 + dbus_source = handler->dbus_source;
271 + dbus_source->ios = g_slist_remove (dbus_source->ios, handler);
272 +
273 + g_source_destroy (handler->source);
274 + g_source_unref (handler->source);
275 + g_free (handler);
276 +}
277 +
278 +static void
279 +dbus_source_add_watch (DBusSource *dbus_source,
280 + DBusWatch *watch)
281 +{
282 + guint flags;
283 + GIOCondition condition;
284 + IOHandler *handler;
285 + int fd;
286 +
287 + if (!dbus_watch_get_enabled (watch))
288 + return;
289 +
290 + g_assert (dbus_watch_get_data (watch) == NULL);
291 +
292 + flags = dbus_watch_get_flags (watch);
293 +
294 + condition = G_IO_ERR | G_IO_HUP;
295 + if (flags & DBUS_WATCH_READABLE)
296 + condition |= G_IO_IN;
297 + if (flags & DBUS_WATCH_WRITABLE)
298 + condition |= G_IO_OUT;
299 +
300 + handler = g_new0 (IOHandler, 1);
301 + handler->dbus_source = dbus_source;
302 + handler->watch = watch;
303 +
304 +#if (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION == 1 && DBUS_MICRO_VERSION >= 1) || (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION > 1) || (DBUS_MAJOR_VERSION > 1)
305 + fd = dbus_watch_get_unix_fd (watch);
306 +#else
307 + fd = dbus_watch_get_fd (watch);
308 +#endif
309 +
310 + handler->source = __g_fd_source_new (fd, condition, NULL);
311 + g_source_set_callback (handler->source,
312 + (GSourceFunc) io_handler_dispatch, handler,
313 + NULL);
314 + g_source_attach (handler->source, NULL);
315 +
316 + dbus_source->ios = g_slist_prepend (dbus_source->ios, handler);
317 + dbus_watch_set_data (watch, handler,
318 + (DBusFreeFunction)io_handler_free);
319 +}
320 +
321 +static void
322 +dbus_source_remove_watch (DBusSource *dbus_source,
323 + DBusWatch *watch)
324 +{
325 + dbus_watch_set_data (watch, NULL, NULL);
326 +}
327 +
328 +static void
329 +timeout_handler_free (TimeoutHandler *handler)
330 +{
331 + DBusSource *dbus_source;
332 +
333 + dbus_source = handler->dbus_source;
334 + dbus_source->timeouts = g_slist_remove (dbus_source->timeouts, handler);
335 +
336 + g_source_destroy (handler->source);
337 + g_source_unref (handler->source);
338 + g_free (handler);
339 +}
340 +
341 +static gboolean
342 +timeout_handler_dispatch (gpointer data)
343 +{
344 + TimeoutHandler *handler = data;
345 +
346 + dbus_timeout_handle (handler->timeout);
347 +
348 + return TRUE;
349 +}
350 +
351 +static void
352 +dbus_source_add_timeout (DBusSource *dbus_source,
353 + DBusTimeout *timeout)
354 +{
355 + TimeoutHandler *handler;
356 +
357 + if (!dbus_timeout_get_enabled (timeout))
358 + return;
359 +
360 + g_assert (dbus_timeout_get_data (timeout) == NULL);
361 +
362 + handler = g_new0 (TimeoutHandler, 1);
363 + handler->dbus_source = dbus_source;
364 + handler->timeout = timeout;
365 +
366 + handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
367 + g_source_set_callback (handler->source,
368 + timeout_handler_dispatch, handler,
369 + NULL);
370 + g_source_attach (handler->source, NULL);
371 +
372 + /* handler->source is owned by the context here */
373 + dbus_source->timeouts = g_slist_prepend (dbus_source->timeouts, handler);
374 +
375 + dbus_timeout_set_data (timeout, handler,
376 + (DBusFreeFunction)timeout_handler_free);
377 +}
378 +
379 +static void
380 +dbus_source_remove_timeout (DBusSource *source,
381 + DBusTimeout *timeout)
382 +{
383 + dbus_timeout_set_data (timeout, NULL, NULL);
384 +}
385 +
386 +static dbus_bool_t
387 +add_watch (DBusWatch *watch,
388 + gpointer data)
389 +{
390 + DBusSource *dbus_source = data;
391 +
392 + dbus_source_add_watch (dbus_source, watch);
393 +
394 + return TRUE;
395 +}
396 +
397 +static void
398 +remove_watch (DBusWatch *watch,
399 + gpointer data)
400 +{
401 + DBusSource *dbus_source = data;
402 +
403 + dbus_source_remove_watch (dbus_source, watch);
404 +}
405 +
406 +static void
407 +watch_toggled (DBusWatch *watch,
408 + void *data)
409 +{
410 + /* Because we just exit on OOM, enable/disable is
411 + * no different from add/remove */
412 + if (dbus_watch_get_enabled (watch))
413 + add_watch (watch, data);
414 + else
415 + remove_watch (watch, data);
416 +}
417 +
418 +static dbus_bool_t
419 +add_timeout (DBusTimeout *timeout,
420 + void *data)
421 +{
422 + DBusSource *source = data;
423 +
424 + if (!dbus_timeout_get_enabled (timeout))
425 + return TRUE;
426 +
427 + dbus_source_add_timeout (source, timeout);
428 +
429 + return TRUE;
430 +}
431 +
432 +static void
433 +remove_timeout (DBusTimeout *timeout,
434 + void *data)
435 +{
436 + DBusSource *source = data;
437 +
438 + dbus_source_remove_timeout (source, timeout);
439 +}
440 +
441 +static void
442 +timeout_toggled (DBusTimeout *timeout,
443 + void *data)
444 +{
445 + /* Because we just exit on OOM, enable/disable is
446 + * no different from add/remove
447 + */
448 + if (dbus_timeout_get_enabled (timeout))
449 + add_timeout (timeout, data);
450 + else
451 + remove_timeout (timeout, data);
452 +}
453 +
454 +static void
455 +wakeup_main (void *data)
456 +{
457 + g_main_context_wakeup (NULL);
458 +}
459 +
460 +static const GSourceFuncs dbus_source_funcs = {
461 + dbus_source_prepare,
462 + dbus_source_check,
463 + dbus_source_dispatch
464 +};
465 +
466 +/* Called when the connection dies or when we're unintegrating from mainloop */
467 +static void
468 +dbus_source_free (DBusSource *dbus_source)
469 +{
470 + while (dbus_source->ios)
471 + {
472 + IOHandler *handler = dbus_source->ios->data;
473 +
474 + dbus_watch_set_data (handler->watch, NULL, NULL);
475 + }
476 +
477 + while (dbus_source->timeouts)
478 + {
479 + TimeoutHandler *handler = dbus_source->timeouts->data;
480 +
481 + dbus_timeout_set_data (handler->timeout, NULL, NULL);
482 + }
483 +
484 + /* Remove from mainloop */
485 + g_source_destroy ((GSource *)dbus_source);
486 +
487 + g_source_unref ((GSource *)dbus_source);
488 +}
489 +
490 +void
491 +_g_dbus_connection_integrate_with_main (DBusConnection *connection)
492 +{
493 + DBusSource *dbus_source;
494 +
495 + g_once (&once_init_main_integration, main_integration_init, NULL);
496 +
497 + g_assert (connection != NULL);
498 +
499 + _g_dbus_connection_remove_from_main (connection);
500 +
501 + dbus_source = (DBusSource *)
502 + g_source_new ((GSourceFuncs*)&dbus_source_funcs,
503 + sizeof (DBusSource));
504 +
505 + dbus_source->connection = connection;
506 +
507 + if (!dbus_connection_set_watch_functions (connection,
508 + add_watch,
509 + remove_watch,
510 + watch_toggled,
511 + dbus_source, NULL))
512 + _g_dbus_oom ();
513 +
514 + if (!dbus_connection_set_timeout_functions (connection,
515 + add_timeout,
516 + remove_timeout,
517 + timeout_toggled,
518 + dbus_source, NULL))
519 + _g_dbus_oom ();
520 +
521 + dbus_connection_set_wakeup_main_function (connection,
522 + wakeup_main,
523 + dbus_source, NULL);
524 +
525 + /* Owned by both connection and mainloop (until destroy) */
526 + g_source_attach ((GSource *)dbus_source, NULL);
527 +
528 + if (!dbus_connection_set_data (connection,
529 + main_integration_data_slot,
530 + dbus_source, (DBusFreeFunction)dbus_source_free))
531 + _g_dbus_oom ();
532 +}
533 +
534 +void
535 +_g_dbus_connection_remove_from_main (DBusConnection *connection)
536 +{
537 + g_once (&once_init_main_integration, main_integration_init, NULL);
538 +
539 + if (!dbus_connection_set_data (connection,
540 + main_integration_data_slot,
541 + NULL, NULL))
542 + _g_dbus_oom ();
543 +}

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain