LCOV - code coverage report
Current view: top level - gio - gcancellable.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 93.2 % 192 179
Test Date: 2025-05-13 05:22:17 Functions: 96.2 % 26 25
Branches: - 0 0

             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                 :      459539 : 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                 :      103214 : g_cancellable_finalize (GObject *object)
      69                 :             : {
      70                 :      103214 :   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                 :      103214 :   if (cancellable->priv->wakeup)
      77                 :           0 :     GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);
      78                 :             : 
      79                 :      103214 :   g_mutex_clear (&cancellable->priv->mutex);
      80                 :             : 
      81                 :      103214 :   G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
      82                 :      103214 : }
      83                 :             : 
      84                 :             : static void
      85                 :         118 : g_cancellable_class_init (GCancellableClass *klass)
      86                 :             : {
      87                 :         118 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
      88                 :             : 
      89                 :         118 :   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                 :         118 :   signals[CANCELLED] =
     148                 :         118 :     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                 :         118 : }
     157                 :             : 
     158                 :             : static void
     159                 :      103537 : g_cancellable_init (GCancellable *cancellable)
     160                 :             : {
     161                 :      103537 :   cancellable->priv = g_cancellable_get_instance_private (cancellable);
     162                 :             : 
     163                 :      103537 :   g_mutex_init (&cancellable->priv->mutex);
     164                 :      103537 : }
     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                 :      103536 : g_cancellable_new (void)
     182                 :             : {
     183                 :      103536 :   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                 :       14810 : g_cancellable_push_current (GCancellable *cancellable)
     201                 :             : {
     202                 :             :   GSList *l;
     203                 :             : 
     204                 :       14810 :   g_return_if_fail (cancellable != NULL);
     205                 :             : 
     206                 :       14810 :   l = g_private_get (&current_cancellable);
     207                 :       14810 :   l = g_slist_prepend (l, cancellable);
     208                 :       14810 :   g_private_set (&current_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                 :       14810 : g_cancellable_pop_current (GCancellable *cancellable)
     220                 :             : {
     221                 :             :   GSList *l;
     222                 :             : 
     223                 :       14810 :   l = g_private_get (&current_cancellable);
     224                 :             : 
     225                 :       14810 :   g_return_if_fail (l != NULL);
     226                 :       14810 :   g_return_if_fail (l->data == cancellable);
     227                 :             : 
     228                 :       14810 :   l = g_slist_delete_link (l, l);
     229                 :       14810 :   g_private_set (&current_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 (&current_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                 :             :  * In the event that a [signal@Gio.Cancellable::cancelled] signal handler is currently
     269                 :             :  * running, this call will block until the handler has finished.
     270                 :             :  * Calling this function from a signal handler will therefore result in a
     271                 :             :  * deadlock.
     272                 :             :  **/
     273                 :             : void 
     274                 :       20273 : g_cancellable_reset (GCancellable *cancellable)
     275                 :             : {
     276                 :             :   GCancellablePrivate *priv;
     277                 :             : 
     278                 :       20273 :   g_return_if_fail (G_IS_CANCELLABLE (cancellable));
     279                 :             : 
     280                 :       20273 :   priv = cancellable->priv;
     281                 :             : 
     282                 :       20273 :   g_mutex_lock (&priv->mutex);
     283                 :             : 
     284                 :       20272 :   if (g_atomic_int_compare_and_exchange (&priv->cancelled, TRUE, FALSE))
     285                 :             :     {
     286                 :          48 :       if (priv->wakeup)
     287                 :           0 :         GLIB_PRIVATE_CALL (g_wakeup_acknowledge) (priv->wakeup);
     288                 :             :     }
     289                 :             : 
     290                 :       20272 :   g_mutex_unlock (&priv->mutex);
     291                 :             : }
     292                 :             : 
     293                 :             : /**
     294                 :             :  * g_cancellable_is_cancelled:
     295                 :             :  * @cancellable: (nullable): a #GCancellable or %NULL
     296                 :             :  *
     297                 :             :  * Checks if a cancellable job has been cancelled.
     298                 :             :  *
     299                 :             :  * Returns: %TRUE if @cancellable is cancelled,
     300                 :             :  * FALSE if called with %NULL or if item is not cancelled.
     301                 :             :  **/
     302                 :             : gboolean
     303                 :      680844 : g_cancellable_is_cancelled (GCancellable *cancellable)
     304                 :             : {
     305                 :      680844 :   return cancellable != NULL && g_atomic_int_get (&cancellable->priv->cancelled);
     306                 :             : }
     307                 :             : 
     308                 :             : /**
     309                 :             :  * g_cancellable_set_error_if_cancelled:
     310                 :             :  * @cancellable: (nullable): a #GCancellable or %NULL
     311                 :             :  * @error: #GError to append error state to
     312                 :             :  *
     313                 :             :  * If the @cancellable is cancelled, sets the error to notify
     314                 :             :  * that the operation was cancelled.
     315                 :             :  *
     316                 :             :  * Returns: %TRUE if @cancellable was cancelled, %FALSE if it was not
     317                 :             :  */
     318                 :             : gboolean
     319                 :      448993 : g_cancellable_set_error_if_cancelled (GCancellable  *cancellable,
     320                 :             :                                       GError       **error)
     321                 :             : {
     322                 :      448993 :   if (g_cancellable_is_cancelled (cancellable))
     323                 :             :     {
     324                 :        4284 :       g_set_error_literal (error,
     325                 :             :                            G_IO_ERROR,
     326                 :             :                            G_IO_ERROR_CANCELLED,
     327                 :             :                            _("Operation was cancelled"));
     328                 :        4284 :       return TRUE;
     329                 :             :     }
     330                 :             : 
     331                 :      444709 :   return FALSE;
     332                 :             : }
     333                 :             : 
     334                 :             : /**
     335                 :             :  * g_cancellable_get_fd:
     336                 :             :  * @cancellable: a #GCancellable.
     337                 :             :  * 
     338                 :             :  * Gets the file descriptor for a cancellable job. This can be used to
     339                 :             :  * implement cancellable operations on Unix systems. The returned fd will
     340                 :             :  * turn readable when @cancellable is cancelled.
     341                 :             :  *
     342                 :             :  * You are not supposed to read from the fd yourself, just check for
     343                 :             :  * readable status. Reading to unset the readable status is done
     344                 :             :  * with g_cancellable_reset().
     345                 :             :  * 
     346                 :             :  * After a successful return from this function, you should use 
     347                 :             :  * g_cancellable_release_fd() to free up resources allocated for 
     348                 :             :  * the returned file descriptor.
     349                 :             :  *
     350                 :             :  * See also g_cancellable_make_pollfd().
     351                 :             :  *
     352                 :             :  * Returns: A valid file descriptor. `-1` if the file descriptor
     353                 :             :  * is not supported, or on errors. 
     354                 :             :  **/
     355                 :             : int
     356                 :           1 : g_cancellable_get_fd (GCancellable *cancellable)
     357                 :             : {
     358                 :             :   GPollFD pollfd;
     359                 :             : #ifndef G_OS_WIN32
     360                 :             :   gboolean retval G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;
     361                 :             : #endif
     362                 :             : 
     363                 :           1 :   if (cancellable == NULL)
     364                 :           0 :           return -1;
     365                 :             : 
     366                 :             : #ifdef G_OS_WIN32
     367                 :             :   pollfd.fd = -1;
     368                 :             : #else
     369                 :           1 :   retval = g_cancellable_make_pollfd (cancellable, &pollfd);
     370                 :           1 :   g_assert (retval);
     371                 :             : #endif
     372                 :             : 
     373                 :           1 :   return pollfd.fd;
     374                 :             : }
     375                 :             : 
     376                 :             : /**
     377                 :             :  * g_cancellable_make_pollfd:
     378                 :             :  * @cancellable: (nullable): a #GCancellable or %NULL
     379                 :             :  * @pollfd: a pointer to a #GPollFD
     380                 :             :  * 
     381                 :             :  * Creates a #GPollFD corresponding to @cancellable; this can be passed
     382                 :             :  * to g_poll() and used to poll for cancellation. This is useful both
     383                 :             :  * for unix systems without a native poll and for portability to
     384                 :             :  * windows.
     385                 :             :  *
     386                 :             :  * When this function returns %TRUE, you should use 
     387                 :             :  * g_cancellable_release_fd() to free up resources allocated for the 
     388                 :             :  * @pollfd. After a %FALSE return, do not call g_cancellable_release_fd().
     389                 :             :  *
     390                 :             :  * If this function returns %FALSE, either no @cancellable was given or
     391                 :             :  * resource limits prevent this function from allocating the necessary 
     392                 :             :  * structures for polling. (On Linux, you will likely have reached 
     393                 :             :  * the maximum number of file descriptors.) The suggested way to handle
     394                 :             :  * these cases is to ignore the @cancellable.
     395                 :             :  *
     396                 :             :  * You are not supposed to read from the fd yourself, just check for
     397                 :             :  * readable status. Reading to unset the readable status is done
     398                 :             :  * with g_cancellable_reset().
     399                 :             :  *
     400                 :             :  * Note that in the event that a [signal@Gio.Cancellable::cancelled] signal handler is
     401                 :             :  * currently running, this call will block until the handler has finished.
     402                 :             :  * Calling this function from a signal handler will therefore result in a
     403                 :             :  * deadlock.
     404                 :             :  *
     405                 :             :  * Returns: %TRUE if @pollfd was successfully initialized, %FALSE on 
     406                 :             :  *          failure to prepare the cancellable.
     407                 :             :  * 
     408                 :             :  * Since: 2.22
     409                 :             :  **/
     410                 :             : gboolean
     411                 :       55204 : g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
     412                 :             : {
     413                 :             :   GCancellablePrivate *priv;
     414                 :             : 
     415                 :       55204 :   g_return_val_if_fail (pollfd != NULL, FALSE);
     416                 :       55204 :   if (cancellable == NULL)
     417                 :       40427 :     return FALSE;
     418                 :       14777 :   g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE);
     419                 :             : 
     420                 :       14777 :   priv = cancellable->priv;
     421                 :             : 
     422                 :       14777 :   g_mutex_lock (&priv->mutex);
     423                 :             : 
     424                 :       14777 :   if ((priv->fd_refcount++) == 0)
     425                 :             :     {
     426                 :       14746 :       priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) ();
     427                 :             : 
     428                 :       14746 :       if (g_atomic_int_get (&priv->cancelled))
     429                 :          40 :         GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
     430                 :             :     }
     431                 :             : 
     432                 :       14777 :   g_assert (priv->wakeup);
     433                 :       14777 :   GLIB_PRIVATE_CALL (g_wakeup_get_pollfd) (priv->wakeup, pollfd);
     434                 :             : 
     435                 :       14777 :   g_mutex_unlock (&priv->mutex);
     436                 :             : 
     437                 :       14777 :   return TRUE;
     438                 :             : }
     439                 :             : 
     440                 :             : /**
     441                 :             :  * g_cancellable_release_fd:
     442                 :             :  * @cancellable: a #GCancellable
     443                 :             :  *
     444                 :             :  * Releases a resources previously allocated by g_cancellable_get_fd()
     445                 :             :  * or g_cancellable_make_pollfd().
     446                 :             :  *
     447                 :             :  * For compatibility reasons with older releases, calling this function 
     448                 :             :  * is not strictly required, the resources will be automatically freed
     449                 :             :  * when the @cancellable is finalized. However, the @cancellable will
     450                 :             :  * block scarce file descriptors until it is finalized if this function
     451                 :             :  * is not called. This can cause the application to run out of file 
     452                 :             :  * descriptors when many #GCancellables are used at the same time.
     453                 :             :  *
     454                 :             :  * Note that in the event that a [signal@Gio.Cancellable::cancelled] signal handler is
     455                 :             :  * currently running, this call will block until the handler has finished.
     456                 :             :  * Calling this function from a signal handler will therefore result in a
     457                 :             :  * deadlock.
     458                 :             :  *
     459                 :             :  * Since: 2.22
     460                 :             :  **/
     461                 :             : void
     462                 :       14777 : g_cancellable_release_fd (GCancellable *cancellable)
     463                 :             : {
     464                 :       14777 :   if (cancellable == NULL)
     465                 :           0 :     return;
     466                 :             : 
     467                 :       14777 :   g_return_if_fail (G_IS_CANCELLABLE (cancellable));
     468                 :             : 
     469                 :       14777 :   g_mutex_lock (&cancellable->priv->mutex);
     470                 :             : 
     471                 :       14777 :   g_assert (cancellable->priv->fd_refcount > 0);
     472                 :             : 
     473                 :       14777 :   if ((cancellable->priv->fd_refcount--) == 1)
     474                 :             :     {
     475                 :       14746 :       GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);
     476                 :       14746 :       cancellable->priv->wakeup = NULL;
     477                 :             :     }
     478                 :             : 
     479                 :       14777 :   g_mutex_unlock (&cancellable->priv->mutex);
     480                 :             : }
     481                 :             : 
     482                 :             : /**
     483                 :             :  * g_cancellable_cancel:
     484                 :             :  * @cancellable: (nullable): a #GCancellable object.
     485                 :             :  * 
     486                 :             :  * Will set @cancellable to cancelled, and will emit the
     487                 :             :  * #GCancellable::cancelled signal. (However, see the warning about
     488                 :             :  * race conditions in the documentation for that signal if you are
     489                 :             :  * planning to connect to it.)
     490                 :             :  *
     491                 :             :  * This function is thread-safe. In other words, you can safely call
     492                 :             :  * it from a thread other than the one running the operation that was
     493                 :             :  * passed the @cancellable.
     494                 :             :  *
     495                 :             :  * If @cancellable is %NULL, this function returns immediately for convenience.
     496                 :             :  *
     497                 :             :  * The convention within GIO is that cancelling an asynchronous
     498                 :             :  * operation causes it to complete asynchronously. That is, if you
     499                 :             :  * cancel the operation from the same thread in which it is running,
     500                 :             :  * then the operation's #GAsyncReadyCallback will not be invoked until
     501                 :             :  * the application returns to the main loop.
     502                 :             :  *
     503                 :             :  * It is safe (although useless, since it will be a no-op) to call
     504                 :             :  * this function from a [signal@Gio.Cancellable::cancelled] signal handler.
     505                 :             :  **/
     506                 :             : void
     507                 :      133352 : g_cancellable_cancel (GCancellable *cancellable)
     508                 :             : {
     509                 :             :   GCancellablePrivate *priv;
     510                 :             : 
     511                 :      133352 :   if (cancellable == NULL || g_atomic_int_get (&cancellable->priv->cancelled))
     512                 :       30145 :     return;
     513                 :             : 
     514                 :      103207 :   priv = cancellable->priv;
     515                 :             : 
     516                 :             :   /* We add a reference before locking, to avoid that potential toggle
     517                 :             :    * notifications on the object might happen while we're locked.
     518                 :             :    */
     519                 :      103207 :   g_object_ref (cancellable);
     520                 :      103207 :   g_mutex_lock (&priv->mutex);
     521                 :             : 
     522                 :      103207 :   if (!g_atomic_int_compare_and_exchange (&priv->cancelled, FALSE, TRUE))
     523                 :             :     {
     524                 :           0 :       g_mutex_unlock (&priv->mutex);
     525                 :           0 :       g_object_unref (cancellable);
     526                 :           0 :       return;
     527                 :             :     }
     528                 :             : 
     529                 :      103207 :   g_atomic_int_inc (&priv->cancelled_running);
     530                 :             : 
     531                 :      103207 :   if (priv->wakeup)
     532                 :           9 :     GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
     533                 :             : 
     534                 :             :   /* Adding another reference, in case the callback is unreffing the
     535                 :             :    * cancellable and there are toggle references, so that the second to last
     536                 :             :    * reference (that would lead a toggle notification) won't be released
     537                 :             :    * while we're locked.
     538                 :             :    */
     539                 :      103207 :   g_object_ref (cancellable);
     540                 :             : 
     541                 :      103207 :   g_signal_emit (cancellable, signals[CANCELLED], 0);
     542                 :             : 
     543                 :      103205 :   if (g_atomic_int_dec_and_test (&priv->cancelled_running))
     544                 :      103205 :     g_cond_broadcast (&cancellable_cond);
     545                 :             : 
     546                 :      103205 :   g_mutex_unlock (&priv->mutex);
     547                 :             : 
     548                 :      103205 :   g_object_unref (cancellable);
     549                 :      103205 :   g_object_unref (cancellable);
     550                 :             : }
     551                 :             : 
     552                 :             : /**
     553                 :             :  * g_cancellable_connect:
     554                 :             :  * @cancellable: A #GCancellable.
     555                 :             :  * @callback: The #GCallback to connect.
     556                 :             :  * @data: Data to pass to @callback.
     557                 :             :  * @data_destroy_func: (nullable): Free function for @data or %NULL.
     558                 :             :  *
     559                 :             :  * Convenience function to connect to the #GCancellable::cancelled
     560                 :             :  * signal. Also handles the race condition that may happen
     561                 :             :  * if the cancellable is cancelled right before connecting.
     562                 :             :  *
     563                 :             :  * @callback is called exactly once each time @cancellable is cancelled,
     564                 :             :  * either directly at the time of the connect if @cancellable is already
     565                 :             :  * cancelled, or when @cancellable is cancelled in some thread.
     566                 :             :  * In case the cancellable is reset via [method@Gio.Cancellable.reset]
     567                 :             :  * then the callback can be called again if the @cancellable is cancelled and
     568                 :             :  * if it had not been previously cancelled at the time
     569                 :             :  * [method@Gio.Cancellable.connect] was called (e.g. if the connection actually
     570                 :             :  * took place, returning a non-zero value).
     571                 :             :  *
     572                 :             :  * @data_destroy_func will be called when the handler is
     573                 :             :  * disconnected, or immediately if the cancellable is already
     574                 :             :  * cancelled.
     575                 :             :  *
     576                 :             :  * See #GCancellable::cancelled for details on how to use this.
     577                 :             :  *
     578                 :             :  * Since GLib 2.40, the lock protecting @cancellable is not held when
     579                 :             :  * @callback is invoked. This lifts a restriction in place for
     580                 :             :  * earlier GLib versions which now makes it easier to write cleanup
     581                 :             :  * code that unconditionally invokes e.g. [method@Gio.Cancellable.cancel].
     582                 :             :  * Note that since 2.82 GLib still holds a lock during the callback but it’s
     583                 :             :  * designed in a way that most of the [class@Gio.Cancellable] methods can be
     584                 :             :  * called, including [method@Gio.Cancellable.cancel] or
     585                 :             :  * [method@GObject.Object.unref].
     586                 :             :  *
     587                 :             :  * There are still some methods that will deadlock (by design) when
     588                 :             :  * called from the [signal@Gio.Cancellable::cancelled] callbacks:
     589                 :             :  *  - [method@Gio.Cancellable.connect]
     590                 :             :  *  - [method@Gio.Cancellable.disconnect]
     591                 :             :  *  - [method@Gio.Cancellable.reset]
     592                 :             :  *  - [method@Gio.Cancellable.make_pollfd]
     593                 :             :  *  - [method@Gio.Cancellable.release_fd]
     594                 :             :  *
     595                 :             :  * Returns: The id of the signal handler or 0 if @cancellable has already
     596                 :             :  *          been cancelled.
     597                 :             :  *
     598                 :             :  * Since: 2.22
     599                 :             :  */
     600                 :             : gulong
     601                 :       10036 : g_cancellable_connect (GCancellable   *cancellable,
     602                 :             :                        GCallback       callback,
     603                 :             :                        gpointer        data,
     604                 :             :                        GDestroyNotify  data_destroy_func)
     605                 :             : {
     606                 :       10036 :   GCancellable *extra_ref = NULL;
     607                 :             :   gulong id;
     608                 :             : 
     609                 :       10036 :   g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), 0);
     610                 :             : 
     611                 :             :   /* If the cancellable is already cancelled we may end up calling the callback
     612                 :             :    * immediately, and the callback may unref the Cancellable, so we need to add
     613                 :             :    * an extra reference here. We can't do it only in the case the cancellable
     614                 :             :    * is already cancelled because it can be potentially be reset, so we can't
     615                 :             :    * rely on the atomic value only, but we need to be locked to be really sure.
     616                 :             :    * At the same time we don't want to wake up the ToggleNotify if toggle
     617                 :             :    * references are enabled while we're locked.
     618                 :             :    */
     619                 :       10036 :   g_object_ref (cancellable);
     620                 :             : 
     621                 :       10036 :   g_mutex_lock (&cancellable->priv->mutex);
     622                 :             : 
     623                 :       10036 :   if (g_atomic_int_get (&cancellable->priv->cancelled))
     624                 :             :     {
     625                 :             :       void (*_callback) (GCancellable *cancellable,
     626                 :             :                          gpointer      user_data);
     627                 :             : 
     628                 :             :       /* Adding another reference, in case the callback is unreffing the
     629                 :             :        * cancellable and there are toggle references, so that the second to last
     630                 :             :        * reference (that would lead a toggle notification) won't be released
     631                 :             :        * while we're locked.
     632                 :             :        */
     633                 :       10006 :       extra_ref = g_object_ref (cancellable);
     634                 :             : 
     635                 :       10006 :       _callback = (void *)callback;
     636                 :       10006 :       id = 0;
     637                 :             : 
     638                 :       10006 :       _callback (cancellable, data);
     639                 :             :     }
     640                 :             :   else
     641                 :             :     {
     642                 :             :       GClosure *closure;
     643                 :             : 
     644                 :          30 :       closure = g_cclosure_new (callback, g_steal_pointer (&data),
     645                 :          30 :                                 (GClosureNotify) g_steal_pointer (&data_destroy_func));
     646                 :             : 
     647                 :          30 :       id = g_signal_connect_closure_by_id (cancellable, signals[CANCELLED],
     648                 :             :                                            0, closure, FALSE);
     649                 :             :     }
     650                 :             : 
     651                 :       10036 :   g_mutex_unlock (&cancellable->priv->mutex);
     652                 :             : 
     653                 :       10036 :   if (data_destroy_func)
     654                 :           3 :     data_destroy_func (data);
     655                 :             : 
     656                 :       10036 :   g_object_unref (cancellable);
     657                 :       10036 :   g_clear_object (&extra_ref);
     658                 :             : 
     659                 :       10036 :   return id;
     660                 :             : }
     661                 :             : 
     662                 :             : /**
     663                 :             :  * g_cancellable_disconnect:
     664                 :             :  * @cancellable: (nullable): A #GCancellable or %NULL.
     665                 :             :  * @handler_id: Handler id of the handler to be disconnected, or `0`.
     666                 :             :  *
     667                 :             :  * Disconnects a handler from a cancellable instance similar to
     668                 :             :  * g_signal_handler_disconnect().  Additionally, in the event that a
     669                 :             :  * signal handler is currently running, this call will block until the
     670                 :             :  * handler has finished.  Calling this function from a
     671                 :             :  * #GCancellable::cancelled signal handler will therefore result in a
     672                 :             :  * deadlock.
     673                 :             :  *
     674                 :             :  * This avoids a race condition where a thread cancels at the
     675                 :             :  * same time as the cancellable operation is finished and the
     676                 :             :  * signal handler is removed. See #GCancellable::cancelled for
     677                 :             :  * details on how to use this.
     678                 :             :  *
     679                 :             :  * If @cancellable is %NULL or @handler_id is `0` this function does
     680                 :             :  * nothing.
     681                 :             :  *
     682                 :             :  * Since: 2.22
     683                 :             :  */
     684                 :             : void
     685                 :       10064 : g_cancellable_disconnect (GCancellable  *cancellable,
     686                 :             :                           gulong         handler_id)
     687                 :             : {
     688                 :             :   GCancellablePrivate *priv;
     689                 :             : 
     690                 :       10064 :   if (handler_id == 0 ||  cancellable == NULL)
     691                 :       10043 :     return;
     692                 :             : 
     693                 :          21 :   priv = cancellable->priv;
     694                 :             : 
     695                 :          21 :   g_mutex_lock (&priv->mutex);
     696                 :             : 
     697                 :          20 :   while (g_atomic_int_get (&priv->cancelled_running) != 0)
     698                 :           0 :     g_cond_wait (&cancellable_cond, &priv->mutex);
     699                 :             : 
     700                 :          20 :   g_mutex_unlock (&priv->mutex);
     701                 :             : 
     702                 :          20 :   g_signal_handler_disconnect (cancellable, handler_id);
     703                 :             : }
     704                 :             : 
     705                 :             : typedef struct {
     706                 :             :   GSource       source;
     707                 :             : 
     708                 :             :   /* Atomic: */
     709                 :             :   GSource     **self_ptr;
     710                 :             :   /* Atomic: */
     711                 :             :   GCancellable *cancellable;
     712                 :             :   gulong        cancelled_handler;
     713                 :             :   /* Atomic: */
     714                 :             :   gboolean      cancelled_callback_called;
     715                 :             : } GCancellableSource;
     716                 :             : 
     717                 :             : /*
     718                 :             :  * The reference count of the GSource might be 0 at this point but it is not
     719                 :             :  * finalized yet and its dispose function did not run yet, or otherwise we
     720                 :             :  * would have disconnected the signal handler already and due to the signal
     721                 :             :  * emission lock it would be impossible to call the signal handler at that
     722                 :             :  * point. That is: at this point we either have a fully valid GSource, or
     723                 :             :  * it's not disposed or finalized yet and we can still resurrect it as needed.
     724                 :             :  *
     725                 :             :  * As such we first ensure that we have a strong reference to the GSource in
     726                 :             :  * here before calling any other GSource API.
     727                 :             :  */
     728                 :             : static void
     729                 :      102756 : cancellable_source_cancelled (GCancellable *cancellable,
     730                 :             :                               gpointer      user_data)
     731                 :             : {
     732                 :      102756 :   GSource *source = g_atomic_pointer_exchange ((GSource **) user_data, NULL);
     733                 :             :   GCancellableSource *cancellable_source;
     734                 :             :   gboolean callback_was_not_called G_GNUC_UNUSED;
     735                 :             : 
     736                 :             :   /* The source is being disposed, so don't bother marking it as ready */
     737                 :      102756 :   if (source == NULL)
     738                 :           1 :     return;
     739                 :             : 
     740                 :      102755 :   cancellable_source = (GCancellableSource *) source;
     741                 :             : 
     742                 :      102755 :   g_source_ref (source);
     743                 :      102755 :   g_source_set_ready_time (source, 0);
     744                 :             : 
     745                 :      102755 :   callback_was_not_called = g_atomic_int_compare_and_exchange (
     746                 :             :     &cancellable_source->cancelled_callback_called, FALSE, TRUE);
     747                 :      102755 :   g_assert (callback_was_not_called);
     748                 :             : 
     749                 :      102755 :   g_source_unref (source);
     750                 :             : }
     751                 :             : 
     752                 :             : static gboolean
     753                 :       60656 : cancellable_source_prepare (GSource *source,
     754                 :             :                             gint    *timeout)
     755                 :             : {
     756                 :       60656 :   GCancellableSource *cancellable_source = (GCancellableSource *) source;
     757                 :             :   GCancellable *cancellable;
     758                 :             : 
     759                 :       60656 :   if (timeout)
     760                 :       60656 :     *timeout = -1;
     761                 :             : 
     762                 :       60656 :   cancellable = g_atomic_pointer_get (&cancellable_source->cancellable);
     763                 :       60656 :   if (cancellable && !g_atomic_int_get (&cancellable->priv->cancelled_running))
     764                 :             :     {
     765                 :       60562 :       g_atomic_int_set (&cancellable_source->cancelled_callback_called, FALSE);
     766                 :       60562 :       g_atomic_pointer_set (cancellable_source->self_ptr, source);
     767                 :             :     }
     768                 :             : 
     769                 :       60656 :   return FALSE;
     770                 :             : }
     771                 :             : 
     772                 :             : static gboolean
     773                 :        2794 : cancellable_source_dispatch (GSource     *source,
     774                 :             :                              GSourceFunc  callback,
     775                 :             :                              gpointer     user_data)
     776                 :             : {
     777                 :        2794 :   GCancellableSourceFunc func = (GCancellableSourceFunc)callback;
     778                 :        2794 :   GCancellableSource *cancellable_source = (GCancellableSource *)source;
     779                 :             : 
     780                 :        2794 :   g_source_set_ready_time (source, -1);
     781                 :        2794 :   return (*func) (cancellable_source->cancellable, user_data);
     782                 :             : }
     783                 :             : 
     784                 :             : static void
     785                 :      117375 : cancellable_source_dispose (GSource *source)
     786                 :             : {
     787                 :      117375 :   GCancellableSource *cancellable_source = (GCancellableSource *)source;
     788                 :             :   GCancellable *cancellable;
     789                 :             : 
     790                 :      117375 :   cancellable = g_atomic_pointer_exchange (&cancellable_source->cancellable, NULL);
     791                 :             : 
     792                 :      117375 :   if (cancellable)
     793                 :             :     {
     794                 :      117375 :       GSource *self_ptr =
     795                 :      117375 :         g_atomic_pointer_exchange (cancellable_source->self_ptr, NULL);
     796                 :             : 
     797                 :      117375 :       if (self_ptr == NULL)
     798                 :             :         {
     799                 :             :           /* There can be a race here: if thread A has called
     800                 :             :            * g_cancellable_cancel() and has got as far as committing to call
     801                 :             :            * cancellable_source_cancelled(), then thread B drops the final
     802                 :             :            * ref on the GCancellableSource before g_source_ref() is called in
     803                 :             :            * cancellable_source_cancelled(), then cancellable_source_dispose()
     804                 :             :            * will run through and the GCancellableSource will be finalised
     805                 :             :            * before cancellable_source_cancelled() gets to g_source_ref(). It
     806                 :             :            * will then be left in a state where it’s committed to using a
     807                 :             :            * dangling GCancellableSource pointer.
     808                 :             :            *
     809                 :             :            * Eliminate that race by waiting to ensure that our cancelled
     810                 :             :            * callback has been called, so that there's no risk that we're
     811                 :             :            * unreffing something that is still going to be used.
     812                 :             :            */
     813                 :             : 
     814                 :      102464 :           while (!g_atomic_int_get (&cancellable_source->cancelled_callback_called))
     815                 :             :             ;
     816                 :             :         }
     817                 :             : 
     818                 :      117375 :       g_clear_signal_handler (&cancellable_source->cancelled_handler, cancellable);
     819                 :      117375 :       g_object_unref (cancellable);
     820                 :             :     }
     821                 :      117375 : }
     822                 :             : 
     823                 :             : static gboolean
     824                 :        2763 : cancellable_source_closure_callback (GCancellable *cancellable,
     825                 :             :                                      gpointer      data)
     826                 :             : {
     827                 :        2763 :   GClosure *closure = data;
     828                 :             : 
     829                 :        2763 :   GValue params = G_VALUE_INIT;
     830                 :        2763 :   GValue result_value = G_VALUE_INIT;
     831                 :             :   gboolean result;
     832                 :             : 
     833                 :        2763 :   g_value_init (&result_value, G_TYPE_BOOLEAN);
     834                 :             : 
     835                 :        2763 :   g_value_init (&params, G_TYPE_CANCELLABLE);
     836                 :        2763 :   g_value_set_object (&params, cancellable);
     837                 :             : 
     838                 :        2763 :   g_closure_invoke (closure, &result_value, 1, &params, NULL);
     839                 :             : 
     840                 :        2763 :   result = g_value_get_boolean (&result_value);
     841                 :        2763 :   g_value_unset (&result_value);
     842                 :        2763 :   g_value_unset (&params);
     843                 :             : 
     844                 :        2763 :   return result;
     845                 :             : }
     846                 :             : 
     847                 :             : static GSourceFuncs cancellable_source_funcs =
     848                 :             : {
     849                 :             :   cancellable_source_prepare,
     850                 :             :   NULL,
     851                 :             :   cancellable_source_dispatch,
     852                 :             :   NULL,
     853                 :             :   (GSourceFunc)cancellable_source_closure_callback,
     854                 :             :   NULL,
     855                 :             : };
     856                 :             : 
     857                 :             : /**
     858                 :             :  * g_cancellable_source_new:
     859                 :             :  * @cancellable: (nullable): a #GCancellable, or %NULL
     860                 :             :  *
     861                 :             :  * Creates a source that triggers if @cancellable is cancelled and
     862                 :             :  * calls its callback of type #GCancellableSourceFunc. This is
     863                 :             :  * primarily useful for attaching to another (non-cancellable) source
     864                 :             :  * with g_source_add_child_source() to add cancellability to it.
     865                 :             :  *
     866                 :             :  * For convenience, you can call this with a %NULL #GCancellable,
     867                 :             :  * in which case the source will never trigger.
     868                 :             :  *
     869                 :             :  * The new #GSource will hold a reference to the #GCancellable.
     870                 :             :  *
     871                 :             :  * Returns: (transfer full): the new #GSource.
     872                 :             :  *
     873                 :             :  * Since: 2.28
     874                 :             :  */
     875                 :             : GSource *
     876                 :      117472 : g_cancellable_source_new (GCancellable *cancellable)
     877                 :             : {
     878                 :             :   GSource *source;
     879                 :             :   GCancellableSource *cancellable_source;
     880                 :             : 
     881                 :      117472 :   source = g_source_new (&cancellable_source_funcs, sizeof (GCancellableSource));
     882                 :      117472 :   g_source_set_static_name (source, "GCancellable");
     883                 :      117472 :   g_source_set_dispose_function (source, cancellable_source_dispose);
     884                 :      117472 :   cancellable_source = (GCancellableSource *)source;
     885                 :             : 
     886                 :      117472 :   if (cancellable)
     887                 :             :     {
     888                 :      117472 :       cancellable_source->cancellable = g_object_ref (cancellable);
     889                 :      117472 :       cancellable_source->self_ptr = g_new (GSource *, 1);
     890                 :      117472 :       g_atomic_pointer_set (cancellable_source->self_ptr, source);
     891                 :             : 
     892                 :             :       /* We intentionally don't use g_cancellable_connect() here,
     893                 :             :        * because we don't want the "at most once" behavior.
     894                 :             :        */
     895                 :      117472 :       cancellable_source->cancelled_handler =
     896                 :      117472 :         g_signal_connect_data (cancellable, "cancelled",
     897                 :             :                                G_CALLBACK (cancellable_source_cancelled),
     898                 :      117472 :                                cancellable_source->self_ptr,
     899                 :             :                                (GClosureNotify) g_free, G_CONNECT_DEFAULT);
     900                 :      117472 :       if (g_cancellable_is_cancelled (cancellable))
     901                 :          58 :         g_source_set_ready_time (source, 0);
     902                 :             :     }
     903                 :             : 
     904                 :      117472 :   return source;
     905                 :             : }
        

Generated by: LCOV version 2.0-1