/**
 * Called to notify the D-Bus library when a previously-added watch is
 * ready for reading or writing, or has an exception such as a hangup.
 * 
 * If this function returns #FALSE, then the file descriptor may still
 * be ready for reading or writing, but more memory is needed in order
 * to do the reading or writing. If you ignore the #FALSE return, your
 * application may spin in a busy loop on the file descriptor until
 * memory becomes available, but nothing more catastrophic should
 * happen.
 *
 * dbus_watch_handle() cannot be called during the
 * DBusAddWatchFunction, as the connection will not be ready to handle
 * that watch yet.
 * 
 * It is not allowed to reference a DBusWatch after it has been passed
 * to remove_function.
 *
 * @param watch the DBusWatch object.
 * @param flags the poll condition using #DBusWatchFlags values
 * @returns #FALSE if there wasn't enough memory 
 */
dbus_bool_t
dbus_watch_handle (DBusWatch    *watch,
                   unsigned int  flags)
{
#ifndef DBUS_DISABLE_CHECKS
  if (watch->fd < 0 || watch->flags == 0)
    {
      _dbus_warn_check_failed ("Watch is invalid, it should have been removed\n");
      return TRUE;
    }
#endif
    
  _dbus_return_val_if_fail (watch->fd >= 0 /* fails if watch was removed */, TRUE);
  
  _dbus_watch_sanitize_condition (watch, &flags);

  if (flags == 0)
    {
      _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
                     watch->fd);
      return TRUE;
    }
  else
    return (* watch->handler) (watch, flags,
                               watch->handler_data);
}
Example #2
0
/**
 * Handles a watch by reading data, writing data, or disconnecting
 * the transport, as appropriate for the given condition.
 *
 * @param transport the transport.
 * @param watch the watch.
 * @param condition the current state of the watched file descriptor.
 * @returns #FALSE if not enough memory to fully handle the watch
 */
dbus_bool_t
_dbus_transport_handle_watch (DBusTransport           *transport,
                              DBusWatch               *watch,
                              unsigned int             condition)
{
  dbus_bool_t retval;
  
  _dbus_assert (transport->vtable->handle_watch != NULL);

  if (transport->disconnected)
    return TRUE;

  if (dbus_watch_get_socket (watch) < 0)
    {
      _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
      return TRUE;
    }
  
  _dbus_watch_sanitize_condition (watch, &condition);

  _dbus_transport_ref (transport);
  _dbus_watch_ref (watch);
  retval = (* transport->vtable->handle_watch) (transport, watch, condition);
  _dbus_watch_unref (watch);
  _dbus_transport_unref (transport);

  return retval;
}
Example #3
0
/**
 * Called to notify the D-Bus library when a previously-added watch is
 * ready for reading or writing, or has an exception such as a hangup.
 * 
 * If this function returns #FALSE, then the file descriptor may still
 * be ready for reading or writing, but more memory is needed in order
 * to do the reading or writing. If you ignore the #FALSE return, your
 * application may spin in a busy loop on the file descriptor until
 * memory becomes available, but nothing more catastrophic should
 * happen.
 *
 * dbus_watch_handle() cannot be called during the
 * DBusAddWatchFunction, as the connection will not be ready to handle
 * that watch yet.
 * 
 * It is not allowed to reference a DBusWatch after it has been passed
 * to remove_function.
 *
 * @param watch the DBusWatch object.
 * @param flags the poll condition using #DBusWatchFlags values
 * @returns #FALSE if there wasn't enough memory 
 */
dbus_bool_t
dbus_watch_handle (DBusWatch    *watch,
                   unsigned int  flags)
{
  _dbus_return_val_if_fail (watch != NULL, FALSE);

#ifndef DBUS_DISABLE_CHECKS
  if (!_dbus_pollable_is_valid (watch->fd) || watch->flags == 0)
    {
      _dbus_warn_check_failed ("Watch is invalid, it should have been removed");
      return TRUE;
    }
#endif
    
  _dbus_return_val_if_fail (_dbus_pollable_is_valid (watch->fd) /* fails if watch was removed */, TRUE);
  
  _dbus_watch_sanitize_condition (watch, &flags);

  if (flags == 0)
    {
      _dbus_verbose ("After sanitization, watch flags on fd %" DBUS_POLLABLE_FORMAT " were 0\n",
                     _dbus_pollable_printable (watch->fd));
      return TRUE;
    }
  else
    return (* watch->handler) (watch, flags,
                               watch->handler_data);
}
Example #4
0
/**
 * Gets the hex-encoded UUID of the machine this function is
 * executed on. This UUID is guaranteed to be the same for a given
 * machine at least until it next reboots, though it also
 * makes some effort to be the same forever, it may change if the
 * machine is reconfigured or its hardware is modified.
 * 
 * @param uuid_str string to append hex-encoded machine uuid to
 * @returns #FALSE if no memory
 */
dbus_bool_t
_dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
{
  dbus_bool_t ok;
  
  _DBUS_LOCK (machine_uuid);
  if (machine_uuid_initialized_generation != _dbus_current_generation)
    {
      DBusError error = DBUS_ERROR_INIT;

      if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
                                          &error))
        {          
#ifndef DBUS_BUILD_TESTS
          /* For the test suite, we may not be installed so just continue silently
           * here. But in a production build, we want to be nice and loud about
           * this.
           */
          _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
                                   "See the manual page for dbus-uuidgen to correct this issue.\n",
                                   error.message);
#endif
          
          dbus_error_free (&error);
          
          _dbus_generate_uuid (&machine_uuid);
        }
    }

  ok = _dbus_uuid_encode (&machine_uuid, uuid_str);

  _DBUS_UNLOCK (machine_uuid);

  return ok;
}
Example #5
0
static void
addresses_shutdown_func (void *data)
{
  int i;

  i = 0;
  while (i < N_BUS_TYPES)
    {
      if (bus_connections[i] != NULL)
        _dbus_warn_check_failed ("dbus_shutdown() called but connections were still live. This probably means the application did not drop all its references to bus connections.\n");
      
      dbus_free (bus_connection_addresses[i]);
      bus_connection_addresses[i] = NULL;
      ++i;
    }

  activation_bus_type = DBUS_BUS_STARTER;
}
Example #6
0
/**
 * Decrements the reference count of a DBusServer.  Finalizes the
 * server if the reference count reaches zero.
 *
 * The server must be disconnected before the refcount reaches zero.
 *
 * @param server the server.
 */
void
dbus_server_unref (DBusServer *server)
{
    dbus_int32_t old_refcount;

    /* keep this in sync with unref_unlocked */

    _dbus_return_if_fail (server != NULL);

    old_refcount = _dbus_atomic_dec (&server->refcount);

#ifndef DBUS_DISABLE_CHECKS
    if (_DBUS_UNLIKELY (old_refcount <= 0))
    {
        /* undo side-effect first
         * please do not try to simplify the code here by using
         * _dbus_atomic_get(), why we don't use it is
         * because it issues another atomic operation even though
         * DBUS_DISABLE_CHECKS defined.
         * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68303
         */
        _dbus_atomic_inc (&server->refcount);
        _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
                                 _DBUS_FUNCTION_NAME, "old_refcount > 0",
                                 __FILE__, __LINE__);
        return;
    }
#endif

    _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref");

    if (old_refcount == 1)
    {
        /* lock not held! */
        _dbus_assert (server->disconnected);

        _dbus_assert (server->vtable->finalize != NULL);

        (* server->vtable->finalize) (server);
    }
}
Example #7
0
EXPORT_C 
#endif
dbus_bool_t
dbus_server_set_timeout_functions (DBusServer                *server,
				   DBusAddTimeoutFunction     add_function,
				   DBusRemoveTimeoutFunction  remove_function,
                                   DBusTimeoutToggledFunction toggled_function,
				   void                      *data,
				   DBusFreeFunction           free_data_function)
{
  dbus_bool_t result;
  DBusTimeoutList *timeouts;
  
  _dbus_return_val_if_fail (server != NULL, FALSE);

  SERVER_LOCK (server);
  timeouts = server->timeouts;
  server->timeouts = NULL;
  if (timeouts)
    {
      SERVER_UNLOCK (server);
      result = _dbus_timeout_list_set_functions (timeouts,
                                                 add_function,
                                                 remove_function,
                                                 toggled_function,
                                                 data,
                                                 free_data_function);
      SERVER_LOCK (server);
    }
  else
    {
      _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
      result = FALSE;
    }
  server->timeouts = timeouts;
  SERVER_UNLOCK (server);
  
  return result;
}
Example #8
0
EXPORT_C 
#endif
dbus_bool_t
dbus_server_set_watch_functions (DBusServer              *server,
                                 DBusAddWatchFunction     add_function,
                                 DBusRemoveWatchFunction  remove_function,
                                 DBusWatchToggledFunction toggled_function,
                                 void                    *data,
                                 DBusFreeFunction         free_data_function)
{
  dbus_bool_t result;
  DBusWatchList *watches;
  
  _dbus_return_val_if_fail (server != NULL, FALSE);

  SERVER_LOCK (server);
  watches = server->watches;
  server->watches = NULL;
  if (watches)
    {
      SERVER_UNLOCK (server);
      result = _dbus_watch_list_set_functions (watches,
                                               add_function,
                                               remove_function,
                                               toggled_function,
                                               data,
                                               free_data_function);
      SERVER_LOCK (server);
    }
  else
    {
      _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
      result = FALSE;
    }
  server->watches = watches;
  SERVER_UNLOCK (server);
  
  return result;
}
Example #9
0
/**
 * Increments the reference count of a DBusServer.
 *
 * @param server the server.
 * @returns the server
 */
DBusServer *
dbus_server_ref (DBusServer *server)
{
    dbus_int32_t old_refcount;

    _dbus_return_val_if_fail (server != NULL, NULL);

    old_refcount = _dbus_atomic_inc (&server->refcount);

#ifndef DBUS_DISABLE_CHECKS
    if (_DBUS_UNLIKELY (old_refcount <= 0))
    {
        _dbus_atomic_dec (&server->refcount);
        _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
                                 _DBUS_FUNCTION_NAME, "old_refcount > 0",
                                 __FILE__, __LINE__);
        return NULL;
    }
#endif

    _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref");

    return server;
}
dbus_bool_t
_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
                                 DBusMutex             **mutex_loc,
                                 dbus_int32_t          *slot_id_p)
{
    dbus_int32_t slot;

    _dbus_mutex_lock (*mutex_loc);

    if (allocator->n_allocated_slots == 0)
    {
        _dbus_assert (allocator->lock_loc == NULL);
        allocator->lock_loc = mutex_loc;
    }
    else if (allocator->lock_loc != mutex_loc)
    {
        _dbus_warn_check_failed ("D-Bus threads were initialized after first using the D-Bus library. If your application does not directly initialize threads or use D-Bus, keep in mind that some library or plugin may have used D-Bus or initialized threads behind your back. You can often fix this problem by calling dbus_init_threads() or dbus_g_threads_init() early in your main() method, before D-Bus is used.\n");
        _dbus_assert_not_reached ("exiting");
    }

    if (*slot_id_p >= 0)
    {
        slot = *slot_id_p;

        _dbus_assert (slot < allocator->n_allocated_slots);
        _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);

        allocator->allocated_slots[slot].refcount += 1;

        goto out;
    }

    _dbus_assert (*slot_id_p < 0);

    if (allocator->n_used_slots < allocator->n_allocated_slots)
    {
        slot = 0;
        while (slot < allocator->n_allocated_slots)
        {
            if (allocator->allocated_slots[slot].slot_id < 0)
            {
                allocator->allocated_slots[slot].slot_id = slot;
                allocator->allocated_slots[slot].refcount = 1;
                allocator->n_used_slots += 1;
                break;
            }
            ++slot;
        }

        _dbus_assert (slot < allocator->n_allocated_slots);
    }
    else
    {
        DBusAllocatedSlot *tmp;

        slot = -1;
        tmp = dbus_realloc (allocator->allocated_slots,
                            sizeof (DBusAllocatedSlot) * (allocator->n_allocated_slots + 1));
        if (tmp == NULL)
            goto out;

        allocator->allocated_slots = tmp;
        slot = allocator->n_allocated_slots;
        allocator->n_allocated_slots += 1;
        allocator->n_used_slots += 1;
        allocator->allocated_slots[slot].slot_id = slot;
        allocator->allocated_slots[slot].refcount = 1;
    }

    _dbus_assert (slot >= 0);
    _dbus_assert (slot < allocator->n_allocated_slots);
    _dbus_assert (*slot_id_p < 0);
    _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
    _dbus_assert (allocator->allocated_slots[slot].refcount == 1);

    *slot_id_p = slot;

    _dbus_verbose ("Allocated slot %d on allocator %p total %d slots allocated %d used\n",
                   slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots);

out:
    _dbus_mutex_unlock (*(allocator->lock_loc));
    return slot >= 0;
}