Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : * Copyright (C) 2022-2024 Canonical, Ltd.
5 : : *
6 : : * SPDX-License-Identifier: LGPL-2.1-or-later
7 : : *
8 : : * This library is free software; you can redistribute it and/or
9 : : * modify it under the terms of the GNU Lesser General Public
10 : : * License as published by the Free Software Foundation; either
11 : : * version 2.1 of the License, or (at your option) any later version.
12 : : *
13 : : * This library is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : : * Lesser General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU Lesser General
19 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 : : *
21 : : * Author: Alexander Larsson <alexl@redhat.com>
22 : : * Author: Marco Trevisan <marco.trevisan@canonical.com>
23 : : */
24 : :
25 : : #include "config.h"
26 : : #include "glib.h"
27 : : #include <gioerror.h>
28 : : #include "glib-private.h"
29 : : #include "gcancellable.h"
30 : : #include "glibintl.h"
31 : :
32 : :
33 : : /**
34 : : * GCancellable:
35 : : *
36 : : * `GCancellable` allows operations to be cancelled.
37 : : *
38 : : * `GCancellable` is a thread-safe operation cancellation stack used
39 : : * throughout GIO to allow for cancellation of synchronous and
40 : : * asynchronous operations.
41 : : */
42 : :
43 : : enum {
44 : : CANCELLED,
45 : : LAST_SIGNAL
46 : : };
47 : :
48 : : struct _GCancellablePrivate
49 : : {
50 : : /* Atomic so that we don't require holding global mutexes for independent ops. */
51 : : gboolean cancelled;
52 : : int cancelled_running;
53 : :
54 : : /* Access to fields below is protected by cancellable's mutex. */
55 : : GMutex mutex;
56 : : guint fd_refcount;
57 : : GWakeup *wakeup;
58 : : };
59 : :
60 : : static guint signals[LAST_SIGNAL] = { 0 };
61 : :
62 : 484106 : G_DEFINE_TYPE_WITH_PRIVATE (GCancellable, g_cancellable, G_TYPE_OBJECT)
63 : :
64 : : static GPrivate current_cancellable;
65 : : static GCond cancellable_cond;
66 : :
67 : : static void
68 : 102146 : g_cancellable_finalize (GObject *object)
69 : : {
70 : 102146 : GCancellable *cancellable = G_CANCELLABLE (object);
71 : :
72 : : /* We're at finalization phase, so only one thread can be here.
73 : : * Thus there's no need to lock. In case something is locking us, then we've
74 : : * a bug, and g_mutex_clear() will make this clear aborting.
75 : : */
76 : 102146 : if (cancellable->priv->wakeup)
77 : 0 : GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);
78 : :
79 : 102146 : g_mutex_clear (&cancellable->priv->mutex);
80 : :
81 : 102146 : G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
82 : 102146 : }
83 : :
84 : : static void
85 : 117 : g_cancellable_class_init (GCancellableClass *klass)
86 : : {
87 : 117 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
88 : :
89 : 117 : gobject_class->finalize = g_cancellable_finalize;
90 : :
91 : : /**
92 : : * GCancellable::cancelled:
93 : : * @cancellable: a #GCancellable.
94 : : *
95 : : * Emitted when the operation has been cancelled.
96 : : *
97 : : * Can be used by implementations of cancellable operations. If the
98 : : * operation is cancelled from another thread, the signal will be
99 : : * emitted in the thread that cancelled the operation, not the
100 : : * thread that is running the operation.
101 : : *
102 : : * Note that disconnecting from this signal (or any signal) in a
103 : : * multi-threaded program is prone to race conditions. For instance
104 : : * it is possible that a signal handler may be invoked even after
105 : : * a call to g_signal_handler_disconnect() for that handler has
106 : : * already returned.
107 : : *
108 : : * There is also a problem when cancellation happens right before
109 : : * connecting to the signal. If this happens the signal will
110 : : * unexpectedly not be emitted, and checking before connecting to
111 : : * the signal leaves a race condition where this is still happening.
112 : : *
113 : : * In order to make it safe and easy to connect handlers there
114 : : * are two helper functions: g_cancellable_connect() and
115 : : * g_cancellable_disconnect() which protect against problems
116 : : * like this.
117 : : *
118 : : * An example of how to us this:
119 : : * |[<!-- language="C" -->
120 : : * // Make sure we don't do unnecessary work if already cancelled
121 : : * if (g_cancellable_set_error_if_cancelled (cancellable, error))
122 : : * return;
123 : : *
124 : : * // Set up all the data needed to be able to handle cancellation
125 : : * // of the operation
126 : : * my_data = my_data_new (...);
127 : : *
128 : : * id = 0;
129 : : * if (cancellable)
130 : : * id = g_cancellable_connect (cancellable,
131 : : * G_CALLBACK (cancelled_handler)
132 : : * data, NULL);
133 : : *
134 : : * // cancellable operation here...
135 : : *
136 : : * g_cancellable_disconnect (cancellable, id);
137 : : *
138 : : * // cancelled_handler is never called after this, it is now safe
139 : : * // to free the data
140 : : * my_data_free (my_data);
141 : : * ]|
142 : : *
143 : : * Note that the cancelled signal is emitted in the thread that
144 : : * the user cancelled from, which may be the main thread. So, the
145 : : * cancellable signal should not do something that can block.
146 : : */
147 : 117 : signals[CANCELLED] =
148 : 117 : g_signal_new (I_("cancelled"),
149 : : G_TYPE_FROM_CLASS (gobject_class),
150 : : G_SIGNAL_RUN_LAST,
151 : : G_STRUCT_OFFSET (GCancellableClass, cancelled),
152 : : NULL, NULL,
153 : : NULL,
154 : : G_TYPE_NONE, 0);
155 : :
156 : 117 : }
157 : :
158 : : static void
159 : 102455 : g_cancellable_init (GCancellable *cancellable)
160 : : {
161 : 102455 : cancellable->priv = g_cancellable_get_instance_private (cancellable);
162 : :
163 : 102455 : g_mutex_init (&cancellable->priv->mutex);
164 : 102455 : }
165 : :
166 : : /**
167 : : * g_cancellable_new:
168 : : *
169 : : * Creates a new #GCancellable object.
170 : : *
171 : : * Applications that want to start one or more operations
172 : : * that should be cancellable should create a #GCancellable
173 : : * and pass it to the operations.
174 : : *
175 : : * One #GCancellable can be used in multiple consecutive
176 : : * operations or in multiple concurrent operations.
177 : : *
178 : : * Returns: a #GCancellable.
179 : : **/
180 : : GCancellable *
181 : 102454 : g_cancellable_new (void)
182 : : {
183 : 102454 : return g_object_new (G_TYPE_CANCELLABLE, NULL);
184 : : }
185 : :
186 : : /**
187 : : * g_cancellable_push_current:
188 : : * @cancellable: a #GCancellable object
189 : : *
190 : : * Pushes @cancellable onto the cancellable stack. The current
191 : : * cancellable can then be received using g_cancellable_get_current().
192 : : *
193 : : * This is useful when implementing cancellable operations in
194 : : * code that does not allow you to pass down the cancellable object.
195 : : *
196 : : * This is typically called automatically by e.g. #GFile operations,
197 : : * so you rarely have to call this yourself.
198 : : **/
199 : : void
200 : 21150 : g_cancellable_push_current (GCancellable *cancellable)
201 : : {
202 : : GSList *l;
203 : :
204 : 21150 : g_return_if_fail (cancellable != NULL);
205 : :
206 : 21150 : l = g_private_get (¤t_cancellable);
207 : 21150 : l = g_slist_prepend (l, cancellable);
208 : 21150 : g_private_set (¤t_cancellable, l);
209 : : }
210 : :
211 : : /**
212 : : * g_cancellable_pop_current:
213 : : * @cancellable: a #GCancellable object
214 : : *
215 : : * Pops @cancellable off the cancellable stack (verifying that @cancellable
216 : : * is on the top of the stack).
217 : : **/
218 : : void
219 : 21150 : g_cancellable_pop_current (GCancellable *cancellable)
220 : : {
221 : : GSList *l;
222 : :
223 : 21150 : l = g_private_get (¤t_cancellable);
224 : :
225 : 21150 : g_return_if_fail (l != NULL);
226 : 21150 : g_return_if_fail (l->data == cancellable);
227 : :
228 : 21150 : l = g_slist_delete_link (l, l);
229 : 21150 : g_private_set (¤t_cancellable, l);
230 : : }
231 : :
232 : : /**
233 : : * g_cancellable_get_current:
234 : : *
235 : : * Gets the top cancellable from the stack.
236 : : *
237 : : * Returns: (nullable) (transfer none): a #GCancellable from the top
238 : : * of the stack, or %NULL if the stack is empty.
239 : : **/
240 : : GCancellable *
241 : 0 : g_cancellable_get_current (void)
242 : : {
243 : : GSList *l;
244 : :
245 : 0 : l = g_private_get (¤t_cancellable);
246 : 0 : if (l == NULL)
247 : 0 : return NULL;
248 : :
249 : 0 : return G_CANCELLABLE (l->data);
250 : : }
251 : :
252 : : /**
253 : : * g_cancellable_reset:
254 : : * @cancellable: a #GCancellable object.
255 : : *
256 : : * Resets @cancellable to its uncancelled state.
257 : : *
258 : : * If cancellable is currently in use by any cancellable operation
259 : : * then the behavior of this function is undefined.
260 : : *
261 : : * Note that it is generally not a good idea to reuse an existing
262 : : * cancellable for more operations after it has been cancelled once,
263 : : * as this function might tempt you to do. The recommended practice
264 : : * is to drop the reference to a cancellable after cancelling it,
265 : : * and let it die with the outstanding async operations. You should
266 : : * create a fresh cancellable for further async operations.
267 : : **/
268 : : void
269 : 20268 : g_cancellable_reset (GCancellable *cancellable)
270 : : {
271 : : GCancellablePrivate *priv;
272 : :
273 : 20268 : g_return_if_fail (G_IS_CANCELLABLE (cancellable));
274 : :
275 : 20268 : priv = cancellable->priv;
276 : :
277 : 20268 : g_mutex_lock (&priv->mutex);
278 : :
279 : 20267 : if (g_atomic_int_compare_and_exchange (&priv->cancelled, TRUE, FALSE))
280 : : {
281 : 38 : if (priv->wakeup)
282 : 0 : GLIB_PRIVATE_CALL (g_wakeup_acknowledge) (priv->wakeup);
283 : : }
284 : :
285 : 20267 : g_mutex_unlock (&priv->mutex);
286 : : }
287 : :
288 : : /**
289 : : * g_cancellable_is_cancelled:
290 : : * @cancellable: (nullable): a #GCancellable or %NULL
291 : : *
292 : : * Checks if a cancellable job has been cancelled.
293 : : *
294 : : * Returns: %TRUE if @cancellable is cancelled,
295 : : * FALSE if called with %NULL or if item is not cancelled.
296 : : **/
297 : : gboolean
298 : 800467 : g_cancellable_is_cancelled (GCancellable *cancellable)
299 : : {
300 : 800467 : return cancellable != NULL && g_atomic_int_get (&cancellable->priv->cancelled);
301 : : }
302 : :
303 : : /**
304 : : * g_cancellable_set_error_if_cancelled:
305 : : * @cancellable: (nullable): a #GCancellable or %NULL
306 : : * @error: #GError to append error state to
307 : : *
308 : : * If the @cancellable is cancelled, sets the error to notify
309 : : * that the operation was cancelled.
310 : : *
311 : : * Returns: %TRUE if @cancellable was cancelled, %FALSE if it was not
312 : : */
313 : : gboolean
314 : 440672 : g_cancellable_set_error_if_cancelled (GCancellable *cancellable,
315 : : GError **error)
316 : : {
317 : 440672 : if (g_cancellable_is_cancelled (cancellable))
318 : : {
319 : 3399 : g_set_error_literal (error,
320 : : G_IO_ERROR,
321 : : G_IO_ERROR_CANCELLED,
322 : : _("Operation was cancelled"));
323 : 3399 : return TRUE;
324 : : }
325 : :
326 : 437273 : return FALSE;
327 : : }
328 : :
329 : : /**
330 : : * g_cancellable_get_fd:
331 : : * @cancellable: a #GCancellable.
332 : : *
333 : : * Gets the file descriptor for a cancellable job. This can be used to
334 : : * implement cancellable operations on Unix systems. The returned fd will
335 : : * turn readable when @cancellable is cancelled.
336 : : *
337 : : * You are not supposed to read from the fd yourself, just check for
338 : : * readable status. Reading to unset the readable status is done
339 : : * with g_cancellable_reset().
340 : : *
341 : : * After a successful return from this function, you should use
342 : : * g_cancellable_release_fd() to free up resources allocated for
343 : : * the returned file descriptor.
344 : : *
345 : : * See also g_cancellable_make_pollfd().
346 : : *
347 : : * Returns: A valid file descriptor. `-1` if the file descriptor
348 : : * is not supported, or on errors.
349 : : **/
350 : : int
351 : 1 : g_cancellable_get_fd (GCancellable *cancellable)
352 : : {
353 : : GPollFD pollfd;
354 : : #ifndef G_OS_WIN32
355 : : gboolean retval G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
356 : : #endif
357 : :
358 : 1 : if (cancellable == NULL)
359 : 0 : return -1;
360 : :
361 : : #ifdef G_OS_WIN32
362 : : pollfd.fd = -1;
363 : : #else
364 : 1 : retval = g_cancellable_make_pollfd (cancellable, &pollfd);
365 : 1 : g_assert (retval);
366 : : #endif
367 : :
368 : 1 : return pollfd.fd;
369 : : }
370 : :
371 : : /**
372 : : * g_cancellable_make_pollfd:
373 : : * @cancellable: (nullable): a #GCancellable or %NULL
374 : : * @pollfd: a pointer to a #GPollFD
375 : : *
376 : : * Creates a #GPollFD corresponding to @cancellable; this can be passed
377 : : * to g_poll() and used to poll for cancellation. This is useful both
378 : : * for unix systems without a native poll and for portability to
379 : : * windows.
380 : : *
381 : : * When this function returns %TRUE, you should use
382 : : * g_cancellable_release_fd() to free up resources allocated for the
383 : : * @pollfd. After a %FALSE return, do not call g_cancellable_release_fd().
384 : : *
385 : : * If this function returns %FALSE, either no @cancellable was given or
386 : : * resource limits prevent this function from allocating the necessary
387 : : * structures for polling. (On Linux, you will likely have reached
388 : : * the maximum number of file descriptors.) The suggested way to handle
389 : : * these cases is to ignore the @cancellable.
390 : : *
391 : : * You are not supposed to read from the fd yourself, just check for
392 : : * readable status. Reading to unset the readable status is done
393 : : * with g_cancellable_reset().
394 : : *
395 : : * Returns: %TRUE if @pollfd was successfully initialized, %FALSE on
396 : : * failure to prepare the cancellable.
397 : : *
398 : : * Since: 2.22
399 : : **/
400 : : gboolean
401 : 64461 : g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
402 : : {
403 : : GCancellablePrivate *priv;
404 : :
405 : 64461 : g_return_val_if_fail (pollfd != NULL, FALSE);
406 : 64461 : if (cancellable == NULL)
407 : 43345 : return FALSE;
408 : 21116 : g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE);
409 : :
410 : 21116 : priv = cancellable->priv;
411 : :
412 : 21116 : g_mutex_lock (&priv->mutex);
413 : :
414 : 21116 : if ((priv->fd_refcount++) == 0)
415 : : {
416 : 21086 : priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) ();
417 : :
418 : 21086 : if (g_atomic_int_get (&priv->cancelled))
419 : 113 : GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
420 : : }
421 : :
422 : 21116 : g_assert (priv->wakeup);
423 : 21116 : GLIB_PRIVATE_CALL (g_wakeup_get_pollfd) (priv->wakeup, pollfd);
424 : :
425 : 21116 : g_mutex_unlock (&priv->mutex);
426 : :
427 : 21116 : return TRUE;
428 : : }
429 : :
430 : : /**
431 : : * g_cancellable_release_fd:
432 : : * @cancellable: a #GCancellable
433 : : *
434 : : * Releases a resources previously allocated by g_cancellable_get_fd()
435 : : * or g_cancellable_make_pollfd().
436 : : *
437 : : * For compatibility reasons with older releases, calling this function
438 : : * is not strictly required, the resources will be automatically freed
439 : : * when the @cancellable is finalized. However, the @cancellable will
440 : : * block scarce file descriptors until it is finalized if this function
441 : : * is not called. This can cause the application to run out of file
442 : : * descriptors when many #GCancellables are used at the same time.
443 : : *
444 : : * Since: 2.22
445 : : **/
446 : : void
447 : 21116 : g_cancellable_release_fd (GCancellable *cancellable)
448 : : {
449 : 21116 : if (cancellable == NULL)
450 : 0 : return;
451 : :
452 : 21116 : g_return_if_fail (G_IS_CANCELLABLE (cancellable));
453 : :
454 : 21116 : g_mutex_lock (&cancellable->priv->mutex);
455 : :
456 : 21116 : g_assert (cancellable->priv->fd_refcount > 0);
457 : :
458 : 21116 : if ((cancellable->priv->fd_refcount--) == 1)
459 : : {
460 : 21086 : GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);
461 : 21086 : cancellable->priv->wakeup = NULL;
462 : : }
463 : :
464 : 21116 : g_mutex_unlock (&cancellable->priv->mutex);
465 : : }
466 : :
467 : : /**
468 : : * g_cancellable_cancel:
469 : : * @cancellable: (nullable): a #GCancellable object.
470 : : *
471 : : * Will set @cancellable to cancelled, and will emit the
472 : : * #GCancellable::cancelled signal. (However, see the warning about
473 : : * race conditions in the documentation for that signal if you are
474 : : * planning to connect to it.)
475 : : *
476 : : * This function is thread-safe. In other words, you can safely call
477 : : * it from a thread other than the one running the operation that was
478 : : * passed the @cancellable.
479 : : *
480 : : * If @cancellable is %NULL, this function returns immediately for convenience.
481 : : *
482 : : * The convention within GIO is that cancelling an asynchronous
483 : : * operation causes it to complete asynchronously. That is, if you
484 : : * cancel the operation from the same thread in which it is running,
485 : : * then the operation's #GAsyncReadyCallback will not be invoked until
486 : : * the application returns to the main loop.
487 : : **/
488 : : void
489 : 122281 : g_cancellable_cancel (GCancellable *cancellable)
490 : : {
491 : : GCancellablePrivate *priv;
492 : :
493 : 122281 : if (cancellable == NULL || g_atomic_int_get (&cancellable->priv->cancelled))
494 : 20139 : return;
495 : :
496 : 102142 : priv = cancellable->priv;
497 : :
498 : : /* We add a reference before locking, to avoid that potential toggle
499 : : * notifications on the object might happen while we're locked.
500 : : */
501 : 102142 : g_object_ref (cancellable);
502 : 102142 : g_mutex_lock (&priv->mutex);
503 : :
504 : 102142 : if (!g_atomic_int_compare_and_exchange (&priv->cancelled, FALSE, TRUE))
505 : : {
506 : 0 : g_mutex_unlock (&priv->mutex);
507 : 0 : g_object_unref (cancellable);
508 : 0 : return;
509 : : }
510 : :
511 : 102142 : g_atomic_int_inc (&priv->cancelled_running);
512 : :
513 : 102142 : if (priv->wakeup)
514 : 9 : GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
515 : :
516 : 102142 : g_signal_emit (cancellable, signals[CANCELLED], 0);
517 : :
518 : 102140 : if (g_atomic_int_dec_and_test (&priv->cancelled_running))
519 : 102140 : g_cond_broadcast (&cancellable_cond);
520 : :
521 : 102140 : g_mutex_unlock (&priv->mutex);
522 : :
523 : 102140 : g_object_unref (cancellable);
524 : : }
525 : :
526 : : /**
527 : : * g_cancellable_connect:
528 : : * @cancellable: A #GCancellable.
529 : : * @callback: The #GCallback to connect.
530 : : * @data: Data to pass to @callback.
531 : : * @data_destroy_func: (nullable): Free function for @data or %NULL.
532 : : *
533 : : * Convenience function to connect to the #GCancellable::cancelled
534 : : * signal. Also handles the race condition that may happen
535 : : * if the cancellable is cancelled right before connecting.
536 : : *
537 : : * @callback is called exactly once each time @cancellable is cancelled,
538 : : * either directly at the time of the connect if @cancellable is already
539 : : * cancelled, or when @cancellable is cancelled in some thread.
540 : : * In case the cancellable is reset via [method@Gio.Cancellable.reset]
541 : : * then the callback can be called again if the @cancellable is cancelled.
542 : : *
543 : : * @data_destroy_func will be called when the handler is
544 : : * disconnected, or immediately if the cancellable is already
545 : : * cancelled.
546 : : *
547 : : * See #GCancellable::cancelled for details on how to use this.
548 : : *
549 : : * Since GLib 2.40, the lock protecting @cancellable is not held when
550 : : * @callback is invoked. This lifts a restriction in place for
551 : : * earlier GLib versions which now makes it easier to write cleanup
552 : : * code that unconditionally invokes e.g. g_cancellable_cancel().
553 : : *
554 : : * Returns: The id of the signal handler or 0 if @cancellable has already
555 : : * been cancelled.
556 : : *
557 : : * Since: 2.22
558 : : */
559 : : gulong
560 : 10025 : g_cancellable_connect (GCancellable *cancellable,
561 : : GCallback callback,
562 : : gpointer data,
563 : : GDestroyNotify data_destroy_func)
564 : : {
565 : : gulong id;
566 : :
567 : 10025 : g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), 0);
568 : :
569 : 10025 : g_mutex_lock (&cancellable->priv->mutex);
570 : :
571 : 10025 : if (g_atomic_int_get (&cancellable->priv->cancelled))
572 : : {
573 : : void (*_callback) (GCancellable *cancellable,
574 : : gpointer user_data);
575 : :
576 : 1 : _callback = (void *)callback;
577 : 1 : id = 0;
578 : :
579 : 1 : _callback (cancellable, data);
580 : :
581 : 1 : if (data_destroy_func)
582 : 1 : data_destroy_func (data);
583 : : }
584 : : else
585 : : {
586 : 10024 : id = g_signal_connect_data (cancellable, "cancelled",
587 : : callback, data,
588 : : (GClosureNotify) data_destroy_func,
589 : : G_CONNECT_DEFAULT);
590 : : }
591 : :
592 : 10025 : g_mutex_unlock (&cancellable->priv->mutex);
593 : :
594 : 10025 : return id;
595 : : }
596 : :
597 : : /**
598 : : * g_cancellable_disconnect:
599 : : * @cancellable: (nullable): A #GCancellable or %NULL.
600 : : * @handler_id: Handler id of the handler to be disconnected, or `0`.
601 : : *
602 : : * Disconnects a handler from a cancellable instance similar to
603 : : * g_signal_handler_disconnect(). Additionally, in the event that a
604 : : * signal handler is currently running, this call will block until the
605 : : * handler has finished. Calling this function from a
606 : : * #GCancellable::cancelled signal handler will therefore result in a
607 : : * deadlock.
608 : : *
609 : : * This avoids a race condition where a thread cancels at the
610 : : * same time as the cancellable operation is finished and the
611 : : * signal handler is removed. See #GCancellable::cancelled for
612 : : * details on how to use this.
613 : : *
614 : : * If @cancellable is %NULL or @handler_id is `0` this function does
615 : : * nothing.
616 : : *
617 : : * Since: 2.22
618 : : */
619 : : void
620 : 10057 : g_cancellable_disconnect (GCancellable *cancellable,
621 : : gulong handler_id)
622 : : {
623 : : GCancellablePrivate *priv;
624 : :
625 : 10057 : if (handler_id == 0 || cancellable == NULL)
626 : 42 : return;
627 : :
628 : 10015 : priv = cancellable->priv;
629 : :
630 : 10015 : g_mutex_lock (&priv->mutex);
631 : :
632 : 10014 : while (g_atomic_int_get (&priv->cancelled_running) != 0)
633 : 0 : g_cond_wait (&cancellable_cond, &priv->mutex);
634 : :
635 : 10014 : g_mutex_unlock (&priv->mutex);
636 : :
637 : 10014 : g_signal_handler_disconnect (cancellable, handler_id);
638 : : }
639 : :
640 : : typedef struct {
641 : : GSource source;
642 : :
643 : : /* Atomic: */
644 : : GCancellable *cancellable;
645 : : gulong cancelled_handler;
646 : : /* Atomic: */
647 : : gboolean cancelled_callback_called;
648 : : } GCancellableSource;
649 : :
650 : : /*
651 : : * The reference count of the GSource might be 0 at this point but it is not
652 : : * finalized yet and its dispose function did not run yet, or otherwise we
653 : : * would have disconnected the signal handler already and due to the signal
654 : : * emission lock it would be impossible to call the signal handler at that
655 : : * point. That is: at this point we either have a fully valid GSource, or
656 : : * it's not disposed or finalized yet and we can still resurrect it as needed.
657 : : *
658 : : * As such we first ensure that we have a strong reference to the GSource in
659 : : * here before calling any other GSource API.
660 : : */
661 : : static void
662 : 78347 : cancellable_source_cancelled (GCancellable *cancellable,
663 : : gpointer user_data)
664 : : {
665 : 78347 : GSource *source = user_data;
666 : 78347 : GCancellableSource *cancellable_source = (GCancellableSource *) source;
667 : : gboolean callback_was_not_called G_GNUC_UNUSED;
668 : :
669 : 78347 : g_source_ref (source);
670 : 78347 : g_source_set_ready_time (source, 0);
671 : :
672 : 78347 : callback_was_not_called = g_atomic_int_compare_and_exchange (
673 : : &cancellable_source->cancelled_callback_called, FALSE, TRUE);
674 : 78347 : g_assert (callback_was_not_called);
675 : :
676 : 78347 : g_source_unref (source);
677 : 78347 : }
678 : :
679 : : static gboolean
680 : 52380 : cancellable_source_prepare (GSource *source,
681 : : gint *timeout)
682 : : {
683 : 52380 : GCancellableSource *cancellable_source = (GCancellableSource *) source;
684 : : GCancellable *cancellable;
685 : :
686 : 52380 : if (timeout)
687 : 52380 : *timeout = -1;
688 : :
689 : 52380 : cancellable = g_atomic_pointer_get (&cancellable_source->cancellable);
690 : 52380 : if (cancellable && !g_atomic_int_get (&cancellable->priv->cancelled_running))
691 : 52346 : g_atomic_int_set (&cancellable_source->cancelled_callback_called, FALSE);
692 : :
693 : 52380 : return FALSE;
694 : : }
695 : :
696 : : static gboolean
697 : 1773 : cancellable_source_dispatch (GSource *source,
698 : : GSourceFunc callback,
699 : : gpointer user_data)
700 : : {
701 : 1773 : GCancellableSourceFunc func = (GCancellableSourceFunc)callback;
702 : 1773 : GCancellableSource *cancellable_source = (GCancellableSource *)source;
703 : :
704 : 1773 : g_source_set_ready_time (source, -1);
705 : 1773 : return (*func) (cancellable_source->cancellable, user_data);
706 : : }
707 : :
708 : : static void
709 : 116385 : cancellable_source_dispose (GSource *source)
710 : : {
711 : 116385 : GCancellableSource *cancellable_source = (GCancellableSource *)source;
712 : : GCancellable *cancellable;
713 : :
714 : 116385 : cancellable = g_atomic_pointer_exchange (&cancellable_source->cancellable, NULL);
715 : :
716 : 116385 : if (cancellable)
717 : : {
718 : 116385 : if (g_atomic_int_get (&cancellable->priv->cancelled_running))
719 : : {
720 : : /* There can be a race here: if thread A has called
721 : : * g_cancellable_cancel() and has got as far as committing to call
722 : : * cancellable_source_cancelled(), then thread B drops the final
723 : : * ref on the GCancellableSource before g_source_ref() is called in
724 : : * cancellable_source_cancelled(), then cancellable_source_dispose()
725 : : * will run through and the GCancellableSource will be finalised
726 : : * before cancellable_source_cancelled() gets to g_source_ref(). It
727 : : * will then be left in a state where it’s committed to using a
728 : : * dangling GCancellableSource pointer.
729 : : *
730 : : * Eliminate that race by waiting to ensure that our cancelled
731 : : * callback has been called, keeping a temporary ref, so that
732 : : * there's no risk that we're unreffing something that is still
733 : : * going to be used.
734 : : */
735 : :
736 : 1067 : g_source_ref (source);
737 : 7659055 : while (!g_atomic_int_get (&cancellable_source->cancelled_callback_called))
738 : : ;
739 : 1067 : g_source_unref (source);
740 : : }
741 : :
742 : 116385 : g_clear_signal_handler (&cancellable_source->cancelled_handler, cancellable);
743 : 116385 : g_object_unref (cancellable);
744 : : }
745 : 116385 : }
746 : :
747 : : static gboolean
748 : 1741 : cancellable_source_closure_callback (GCancellable *cancellable,
749 : : gpointer data)
750 : : {
751 : 1741 : GClosure *closure = data;
752 : :
753 : 1741 : GValue params = G_VALUE_INIT;
754 : 1741 : GValue result_value = G_VALUE_INIT;
755 : : gboolean result;
756 : :
757 : 1741 : g_value_init (&result_value, G_TYPE_BOOLEAN);
758 : :
759 : 1741 : g_value_init (¶ms, G_TYPE_CANCELLABLE);
760 : 1741 : g_value_set_object (¶ms, cancellable);
761 : :
762 : 1741 : g_closure_invoke (closure, &result_value, 1, ¶ms, NULL);
763 : :
764 : 1741 : result = g_value_get_boolean (&result_value);
765 : 1741 : g_value_unset (&result_value);
766 : 1741 : g_value_unset (¶ms);
767 : :
768 : 1741 : return result;
769 : : }
770 : :
771 : : static GSourceFuncs cancellable_source_funcs =
772 : : {
773 : : cancellable_source_prepare,
774 : : NULL,
775 : : cancellable_source_dispatch,
776 : : NULL,
777 : : (GSourceFunc)cancellable_source_closure_callback,
778 : : NULL,
779 : : };
780 : :
781 : : /**
782 : : * g_cancellable_source_new:
783 : : * @cancellable: (nullable): a #GCancellable, or %NULL
784 : : *
785 : : * Creates a source that triggers if @cancellable is cancelled and
786 : : * calls its callback of type #GCancellableSourceFunc. This is
787 : : * primarily useful for attaching to another (non-cancellable) source
788 : : * with g_source_add_child_source() to add cancellability to it.
789 : : *
790 : : * For convenience, you can call this with a %NULL #GCancellable,
791 : : * in which case the source will never trigger.
792 : : *
793 : : * The new #GSource will hold a reference to the #GCancellable.
794 : : *
795 : : * Returns: (transfer full): the new #GSource.
796 : : *
797 : : * Since: 2.28
798 : : */
799 : : GSource *
800 : 116466 : g_cancellable_source_new (GCancellable *cancellable)
801 : : {
802 : : GSource *source;
803 : : GCancellableSource *cancellable_source;
804 : :
805 : 116466 : source = g_source_new (&cancellable_source_funcs, sizeof (GCancellableSource));
806 : 116466 : g_source_set_static_name (source, "GCancellable");
807 : 116466 : g_source_set_dispose_function (source, cancellable_source_dispose);
808 : 116466 : cancellable_source = (GCancellableSource *)source;
809 : :
810 : 116466 : if (cancellable)
811 : : {
812 : 116466 : cancellable_source->cancellable = g_object_ref (cancellable);
813 : :
814 : : /* We intentionally don't use g_cancellable_connect() here,
815 : : * because we don't want the "at most once" behavior.
816 : : */
817 : 116466 : cancellable_source->cancelled_handler =
818 : 116466 : g_signal_connect (cancellable, "cancelled",
819 : : G_CALLBACK (cancellable_source_cancelled),
820 : : source);
821 : 116466 : if (g_cancellable_is_cancelled (cancellable))
822 : 31 : g_source_set_ready_time (source, 0);
823 : : }
824 : :
825 : 116466 : return source;
826 : : }
|