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