示例#1
0
/**
 * g_cancellable_make_pollfd:
 * @cancellable: (allow-none): a #GCancellable or %NULL
 * @pollfd: a pointer to a #GPollFD
 * 
 * Creates a #GPollFD corresponding to @cancellable; this can be passed
 * to g_poll() and used to poll for cancellation. This is useful both
 * for unix systems without a native poll and for portability to
 * windows.
 *
 * When this function returns %TRUE, you should use 
 * g_cancellable_release_fd() to free up resources allocated for the 
 * @pollfd. After a %FALSE return, do not call g_cancellable_release_fd().
 *
 * If this function returns %FALSE, either no @cancellable was given or
 * resource limits prevent this function from allocating the necessary 
 * structures for polling. (On Linux, you will likely have reached 
 * the maximum number of file descriptors.) The suggested way to handle
 * these cases is to ignore the @cancellable.
 *
 * You are not supposed to read from the fd yourself, just check for
 * readable status. Reading to unset the readable status is done
 * with g_cancellable_reset().
 *
 * Returns: %TRUE if @pollfd was successfully initialized, %FALSE on 
 *          failure to prepare the cancellable.
 * 
 * Since: 2.22
 **/
gboolean
g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
{
  g_return_val_if_fail (pollfd != NULL, FALSE);
  if (cancellable == NULL)
    return FALSE;
  g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE);

  g_mutex_lock (&cancellable_mutex);

  cancellable->priv->fd_refcount++;

  if (cancellable->priv->wakeup == NULL)
    {
      cancellable->priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) ();

      if (cancellable->priv->cancelled)
        GLIB_PRIVATE_CALL (g_wakeup_signal) (cancellable->priv->wakeup);
    }

  GLIB_PRIVATE_CALL (g_wakeup_get_pollfd) (cancellable->priv->wakeup, pollfd);

  g_mutex_unlock (&cancellable_mutex);

  return TRUE;
}
示例#2
0
/**
 * g_cancellable_reset:
 * @cancellable: a #GCancellable object.
 * 
 * Resets @cancellable to its uncancelled state.
 *
 * If cancellable is currently in use by any cancellable operation
 * then the behavior of this function is undefined.
 **/
void 
g_cancellable_reset (GCancellable *cancellable)
{
  GCancellablePrivate *priv;

  g_return_if_fail (G_IS_CANCELLABLE (cancellable));

  g_mutex_lock (&cancellable_mutex);

  priv = cancellable->priv;

  while (priv->cancelled_running)
    {
      priv->cancelled_running_waiting = TRUE;
      g_cond_wait (&cancellable_cond, &cancellable_mutex);
    }

  if (priv->cancelled)
    {
      if (priv->wakeup)
        GLIB_PRIVATE_CALL (g_wakeup_acknowledge) (priv->wakeup);

      priv->cancelled = FALSE;
    }

  g_mutex_unlock (&cancellable_mutex);
}
示例#3
0
static gboolean
g_fam_file_monitor_is_supported (void)
{
  g_mutex_lock (&fam_lock);

  if (!fam_initialised)
    {
      fam_initialised = FAMOpen2 (&fam_connection, "GLib GIO") == 0;

      if (fam_initialised)
        {
#ifdef HAVE_FAM_NO_EXISTS
          /* This is a gamin extension that avoids sending all the
           * Exists event for dir monitors
           */
          FAMNoExists (&fam_connection);
#endif

          fam_source = g_unix_fd_source_new (FAMCONNECTION_GETFD (&fam_connection), G_IO_IN);
          g_source_set_callback (fam_source, (GSourceFunc) g_fam_file_monitor_callback, NULL, NULL);
          g_source_attach (fam_source, GLIB_PRIVATE_CALL(g_get_worker_context) ());
        }
    }

  g_mutex_unlock (&fam_lock);

  g_print ("II %d\n", fam_initialised);

  return fam_initialised;
}
示例#4
0
static void
g_cancellable_finalize (GObject *object)
{
  GCancellable *cancellable = G_CANCELLABLE (object);

  if (cancellable->priv->wakeup)
    GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);

  G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
}
示例#5
0
/**
 * g_cancellable_cancel:
 * @cancellable: a #GCancellable object.
 * 
 * Will set @cancellable to cancelled, and will emit the
 * #GCancellable::cancelled signal. (However, see the warning about
 * race conditions in the documentation for that signal if you are
 * planning to connect to it.)
 *
 * This function is thread-safe. In other words, you can safely call
 * it from a thread other than the one running the operation that was
 * passed the @cancellable.
 *
 * The convention within gio is that cancelling an asynchronous
 * operation causes it to complete asynchronously. That is, if you
 * cancel the operation from the same thread in which it is running,
 * then the operation's #GAsyncReadyCallback will not be invoked until
 * the application returns to the main loop.
 **/
void
g_cancellable_cancel (GCancellable *cancellable)
{
  GCancellablePrivate *priv;

  if (cancellable == NULL ||
      cancellable->priv->cancelled)
    return;

  priv = cancellable->priv;

  g_mutex_lock (&cancellable_mutex);

  if (priv->cancelled)
    {
      g_mutex_unlock (&cancellable_mutex);
      return;
    }

  priv->cancelled = TRUE;
  priv->cancelled_running = TRUE;

  if (priv->wakeup)
    GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);

  g_mutex_unlock (&cancellable_mutex);

  g_object_ref (cancellable);
  g_signal_emit (cancellable, signals[CANCELLED], 0);

  g_mutex_lock (&cancellable_mutex);

  priv->cancelled_running = FALSE;
  if (priv->cancelled_running_waiting)
    g_cond_broadcast (&cancellable_cond);
  priv->cancelled_running_waiting = FALSE;

  g_mutex_unlock (&cancellable_mutex);

  g_object_unref (cancellable);
}
示例#6
0
/**
 * g_cancellable_release_fd:
 * @cancellable: a #GCancellable
 *
 * Releases a resources previously allocated by g_cancellable_get_fd()
 * or g_cancellable_make_pollfd().
 *
 * For compatibility reasons with older releases, calling this function 
 * is not strictly required, the resources will be automatically freed
 * when the @cancellable is finalized. However, the @cancellable will
 * block scarce file descriptors until it is finalized if this function
 * is not called. This can cause the application to run out of file 
 * descriptors when many #GCancellables are used at the same time.
 * 
 * Since: 2.22
 **/
void
g_cancellable_release_fd (GCancellable *cancellable)
{
  GCancellablePrivate *priv;

  if (cancellable == NULL)
    return;

  g_return_if_fail (G_IS_CANCELLABLE (cancellable));
  g_return_if_fail (cancellable->priv->fd_refcount > 0);

  priv = cancellable->priv;

  g_mutex_lock (&cancellable_mutex);

  priv->fd_refcount--;
  if (priv->fd_refcount == 0)
    {
      GLIB_PRIVATE_CALL (g_wakeup_free) (priv->wakeup);
      priv->wakeup = NULL;
    }

  g_mutex_unlock (&cancellable_mutex);
}
示例#7
0
/* inotify_lock must be held before calling */
void
_im_add (inotify_sub *sub)
{
  if (g_list_find (missing_sub_list, sub))
    {
      IM_W ("asked to add %s to missing list but it's already on the list!\n", sub->dirname);
      return;
    }

  IM_W ("adding %s to missing list\n", sub->dirname);
  missing_sub_list = g_list_prepend (missing_sub_list, sub);

  /* If the timeout is turned off, we turn it back on */
  if (!scan_missing_running)
    {
      GSource *source;

      scan_missing_running = TRUE;
      source = g_timeout_source_new_seconds (SCAN_MISSING_TIME);
      g_source_set_callback (source, im_scan_missing, NULL, NULL);
      g_source_attach (source, GLIB_PRIVATE_CALL (g_get_worker_context) ());
      g_source_unref (source);
    }
}
示例#8
0
static gchar *
get_session_address_dbus_launch (GError **error)
{
  gchar *ret;
  gchar *machine_id;
  gchar *command_line;
  gchar *launch_stdout;
  gchar *launch_stderr;
  gint exit_status;
  gchar *old_dbus_verbose;
  gboolean restore_dbus_verbose;

  ret = NULL;
  machine_id = NULL;
  command_line = NULL;
  launch_stdout = NULL;
  launch_stderr = NULL;
  restore_dbus_verbose = FALSE;
  old_dbus_verbose = NULL;

  /* Don't run binaries as root if we're setuid. */
  if (GLIB_PRIVATE_CALL (g_check_setuid) ())
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
		   _("Cannot spawn a message bus when setuid"));
      goto out;
    }

  machine_id = _g_dbus_get_machine_id (error);
  if (machine_id == NULL)
    {
      g_prefix_error (error, _("Cannot spawn a message bus without a machine-id: "));
      goto out;
    }

  /* We're using private libdbus facilities here. When everything
   * (X11, Mac OS X, Windows) is spec'ed out correctly (not even the
   * X11 property is correctly documented right now) we should
   * consider using the spec instead of dbus-launch.
   *
   *   --autolaunch=MACHINEID
   *          This option implies that dbus-launch should scan  for  a  previ‐
   *          ously-started  session  and  reuse the values found there. If no
   *          session is found, it will start a new session. The  --exit-with-
   *          session option is implied if --autolaunch is given.  This option
   *          is for the exclusive use of libdbus, you do not want to  use  it
   *          manually. It may change in the future.
   */

  /* TODO: maybe provide a variable for where to look for the dbus-launch binary? */
  command_line = g_strdup_printf ("dbus-launch --autolaunch=%s --binary-syntax --close-stderr", machine_id);

  if (G_UNLIKELY (_g_dbus_debug_address ()))
    {
      _g_dbus_debug_print_lock ();
      g_print ("GDBus-debug:Address: Running '%s' to get bus address (possibly autolaunching)\n", command_line);
      old_dbus_verbose = g_strdup (g_getenv ("DBUS_VERBOSE"));
      restore_dbus_verbose = TRUE;
      g_setenv ("DBUS_VERBOSE", "1", TRUE);
      _g_dbus_debug_print_unlock ();
    }

  if (!g_spawn_command_line_sync (command_line,
                                  &launch_stdout,
                                  &launch_stderr,
                                  &exit_status,
                                  error))
    {
      goto out;
    }

  if (!g_spawn_check_exit_status (exit_status, error))
    {
      g_prefix_error (error, _("Error spawning command line '%s': "), command_line);
      goto out;
    }

  /* From the dbus-launch(1) man page:
   *
   *   --binary-syntax Write to stdout a nul-terminated bus address,
   *   then the bus PID as a binary integer of size sizeof(pid_t),
   *   then the bus X window ID as a binary integer of size
   *   sizeof(long).  Integers are in the machine's byte order, not
   *   network byte order or any other canonical byte order.
   */
  ret = g_strdup (launch_stdout);

 out:
  if (G_UNLIKELY (_g_dbus_debug_address ()))
    {
      gchar *s;
      _g_dbus_debug_print_lock ();
      g_print ("GDBus-debug:Address: dbus-launch output:");
      if (launch_stdout != NULL)
        {
          s = _g_dbus_hexdump (launch_stdout, strlen (launch_stdout) + 1 + sizeof (pid_t) + sizeof (long), 2);
          g_print ("\n%s", s);
          g_free (s);
        }
      else
        {
          g_print (" (none)\n");
        }
      g_print ("GDBus-debug:Address: dbus-launch stderr output:");
      if (launch_stderr != NULL)
        g_print ("\n%s", launch_stderr);
      else
        g_print (" (none)\n");
      _g_dbus_debug_print_unlock ();
    }

  g_free (machine_id);
  g_free (command_line);
  g_free (launch_stdout);
  g_free (launch_stderr);
  if (G_UNLIKELY (restore_dbus_verbose))
    {
      if (old_dbus_verbose != NULL)
        g_setenv ("DBUS_VERBOSE", old_dbus_verbose, TRUE);
      else
        g_unsetenv ("DBUS_VERBOSE");
    }
  g_free (old_dbus_verbose);
  return ret;
}