2010-05-06 20:13:59 +02:00
/* GDBus - GLib D-Bus Library
*
2010-05-09 19:14:55 +02:00
* Copyright ( C ) 2008 - 2010 Red Hat , Inc .
2010-05-06 20:13:59 +02:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place , Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*
* Author : David Zeuthen < davidz @ redhat . com >
*/
# include "config.h"
# include <stdlib.h>
2010-05-06 22:34:23 +02:00
# include <string.h>
2010-05-06 20:13:59 +02:00
# include "gdbusutils.h"
# include "gdbusproxy.h"
# include "gioenumtypes.h"
# include "gdbusconnection.h"
# include "gdbuserror.h"
# include "gdbusprivate.h"
# include "ginitable.h"
# include "gasyncinitable.h"
# include "gioerror.h"
# include "gasyncresult.h"
# include "gsimpleasyncresult.h"
2010-06-11 21:45:18 +02:00
# include "gcancellable.h"
2011-04-08 21:14:47 +02:00
# include "gdbusinterface.h"
2010-05-06 20:13:59 +02:00
2011-07-21 22:03:27 +02:00
# ifdef G_OS_UNIX
# include "gunixfdlist.h"
# endif
2010-05-06 22:34:23 +02:00
# include "glibintl.h"
2010-05-06 20:13:59 +02:00
/**
* SECTION : gdbusproxy
2011-04-08 22:12:09 +02:00
* @ short_description : Client - side D - Bus interface proxy
2010-05-06 21:31:45 +02:00
* @ include : gio / gio . h
2010-05-06 20:13:59 +02:00
*
* # GDBusProxy is a base class used for proxies to access a D - Bus
2010-06-11 21:45:18 +02:00
* interface on a remote object . A # GDBusProxy can be constructed for
* both well - known and unique names .
2010-05-14 03:45:18 +02:00
*
2010-06-11 21:45:18 +02:00
* By default , # GDBusProxy will cache all properties ( and listen to
* changes ) of the remote object , and proxy all signals that gets
2010-05-14 03:45:18 +02:00
* emitted . This behaviour can be changed by passing suitable
2010-06-11 21:45:18 +02:00
* # GDBusProxyFlags when the proxy is created . If the proxy is for a
* well - known name , the property cache is flushed when the name owner
* vanishes and reloaded when a name owner appears .
*
* If a # GDBusProxy is used for a well - known name , the owner of the
* name is tracked and can be read from
* # GDBusProxy : g - name - owner . Connect to the # GObject : : notify signal to
* get notified of changes . Additionally , only signals and property
2010-08-18 17:35:25 +02:00
* changes emitted from the current name owner are considered and
* calls are always sent to the current name owner . This avoids a
* number of race conditions when the name is lost by one owner and
* claimed by another . However , if no name owner currently exists ,
* then calls will be sent to the well - known name which may result in
* the message bus launching an owner ( unless
* % G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START is set ) .
2010-05-14 03:45:18 +02:00
*
2011-05-26 16:18:44 +02:00
* The generic # GDBusProxy : : g - properties - changed and
* # GDBusProxy : : g - signal signals are not very convenient to work
* with . Therefore , the recommended way of working with proxies is to
* subclass # GDBusProxy , and have more natural properties and signals
* in your derived class . See < xref linkend = " gdbus-example-gdbus-codegen " / >
* for how this can easily be done using the
* < command > < link linkend = " gdbus-codegen " > gdbus - codegen < / link > < / command >
* tool .
2010-05-14 03:45:18 +02:00
*
2011-05-26 15:54:47 +02:00
* A # GDBusProxy instance can be used from multiple threads but note
2011-05-26 16:18:44 +02:00
* that all signals ( e . g . # GDBusProxy : : g - signal , # GDBusProxy : : g - properties - changed
2011-05-26 15:54:47 +02:00
* and # GObject : : notify ) are emitted in the
* < link linkend = " g-main-context-push-thread-default " > thread - default main loop < / link >
* of the thread where the instance was constructed .
*
2010-06-11 21:45:18 +02:00
* < example id = " gdbus-wellknown-proxy " > < title > GDBusProxy for a well - known - name < / title > < programlisting > < xi : include xmlns : xi = " http://www.w3.org/2001/XInclude " parse = " text " href = " ../../../../gio/tests/gdbus-example-watch-proxy.c " > < xi : fallback > FIXME : MISSING XINCLUDE CONTENT < / xi : fallback > < / xi : include > < / programlisting > < / example >
2010-05-06 20:13:59 +02:00
*/
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* lock protecting the mutable properties: name_owner, timeout_msec,
* expected_interface , and the properties hash table
*/
2011-05-26 15:54:47 +02:00
G_LOCK_DEFINE_STATIC ( properties_lock ) ;
2011-05-26 15:26:29 +02:00
/* ---------------------------------------------------------------------------------------------------- */
G_LOCK_DEFINE_STATIC ( signal_subscription_lock ) ;
typedef struct
{
volatile gint ref_count ;
GDBusProxy * proxy ;
} SignalSubscriptionData ;
static SignalSubscriptionData *
signal_subscription_ref ( SignalSubscriptionData * data )
{
g_atomic_int_inc ( & data - > ref_count ) ;
return data ;
}
static void
signal_subscription_unref ( SignalSubscriptionData * data )
{
if ( g_atomic_int_dec_and_test ( & data - > ref_count ) )
{
g_slice_free ( SignalSubscriptionData , data ) ;
}
}
/* ---------------------------------------------------------------------------------------------------- */
2010-05-06 20:13:59 +02:00
struct _GDBusProxyPrivate
{
2010-06-11 21:45:18 +02:00
GBusType bus_type ;
2011-04-12 16:00:37 +02:00
GDBusProxyFlags flags ;
2010-05-06 20:13:59 +02:00
GDBusConnection * connection ;
2010-06-11 21:45:18 +02:00
gchar * name ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* mutable, protected by properties_lock */
2010-06-11 21:45:18 +02:00
gchar * name_owner ;
2010-05-06 20:13:59 +02:00
gchar * object_path ;
gchar * interface_name ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* mutable, protected by properties_lock */
2010-05-06 20:13:59 +02:00
gint timeout_msec ;
2010-06-11 21:45:18 +02:00
guint name_owner_changed_subscription_id ;
GCancellable * get_all_cancellable ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* gchar* -> GVariant*, protected by properties_lock */
2010-05-06 20:13:59 +02:00
GHashTable * properties ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* mutable, protected by properties_lock */
2010-05-06 20:13:59 +02:00
GDBusInterfaceInfo * expected_interface ;
2011-05-26 15:26:29 +02:00
guint properties_changed_subscription_id ;
guint signals_subscription_id ;
2010-05-13 23:20:39 +02:00
gboolean initialized ;
2011-04-08 22:12:33 +02:00
2012-01-26 20:16:28 +01:00
/* mutable, protected by properties_lock */
2011-04-08 22:12:33 +02:00
GDBusObject * object ;
2011-05-26 15:26:29 +02:00
SignalSubscriptionData * signal_subscription_data ;
2010-05-06 20:13:59 +02:00
} ;
enum
{
PROP_0 ,
PROP_G_CONNECTION ,
2010-06-11 21:45:18 +02:00
PROP_G_BUS_TYPE ,
PROP_G_NAME ,
PROP_G_NAME_OWNER ,
2010-05-06 20:13:59 +02:00
PROP_G_FLAGS ,
PROP_G_OBJECT_PATH ,
PROP_G_INTERFACE_NAME ,
PROP_G_DEFAULT_TIMEOUT ,
PROP_G_INTERFACE_INFO
} ;
enum
{
PROPERTIES_CHANGED_SIGNAL ,
SIGNAL_SIGNAL ,
LAST_SIGNAL ,
} ;
2012-02-24 02:12:08 +01:00
static guint signals [ LAST_SIGNAL ] = { 0 } ;
2010-05-06 20:13:59 +02:00
2011-04-08 21:14:47 +02:00
static void dbus_interface_iface_init ( GDBusInterfaceIface * dbus_interface_iface ) ;
2010-05-06 20:13:59 +02:00
static void initable_iface_init ( GInitableIface * initable_iface ) ;
static void async_initable_iface_init ( GAsyncInitableIface * async_initable_iface ) ;
G_DEFINE_TYPE_WITH_CODE ( GDBusProxy , g_dbus_proxy , G_TYPE_OBJECT ,
2011-04-08 21:14:47 +02:00
G_IMPLEMENT_INTERFACE ( G_TYPE_DBUS_INTERFACE , dbus_interface_iface_init )
2010-05-06 20:13:59 +02:00
G_IMPLEMENT_INTERFACE ( G_TYPE_INITABLE , initable_iface_init )
G_IMPLEMENT_INTERFACE ( G_TYPE_ASYNC_INITABLE , async_initable_iface_init )
) ;
2011-05-26 15:26:29 +02:00
static void
g_dbus_proxy_dispose ( GObject * object )
{
GDBusProxy * proxy = G_DBUS_PROXY ( object ) ;
G_LOCK ( signal_subscription_lock ) ;
if ( proxy - > priv - > signal_subscription_data ! = NULL )
{
proxy - > priv - > signal_subscription_data - > proxy = NULL ;
signal_subscription_unref ( proxy - > priv - > signal_subscription_data ) ;
proxy - > priv - > signal_subscription_data = NULL ;
}
G_UNLOCK ( signal_subscription_lock ) ;
G_OBJECT_CLASS ( g_dbus_proxy_parent_class ) - > dispose ( object ) ;
}
2010-05-06 20:13:59 +02:00
static void
g_dbus_proxy_finalize ( GObject * object )
{
GDBusProxy * proxy = G_DBUS_PROXY ( object ) ;
2010-06-11 21:45:18 +02:00
g_warn_if_fail ( proxy - > priv - > get_all_cancellable = = NULL ) ;
if ( proxy - > priv - > name_owner_changed_subscription_id > 0 )
g_dbus_connection_signal_unsubscribe ( proxy - > priv - > connection ,
proxy - > priv - > name_owner_changed_subscription_id ) ;
2011-05-26 15:26:29 +02:00
if ( proxy - > priv - > properties_changed_subscription_id > 0 )
2010-05-10 04:13:18 +02:00
g_dbus_connection_signal_unsubscribe ( proxy - > priv - > connection ,
2011-05-26 15:26:29 +02:00
proxy - > priv - > properties_changed_subscription_id ) ;
2010-05-06 20:13:59 +02:00
2011-05-26 15:26:29 +02:00
if ( proxy - > priv - > signals_subscription_id > 0 )
2010-05-10 04:13:18 +02:00
g_dbus_connection_signal_unsubscribe ( proxy - > priv - > connection ,
2011-05-26 15:26:29 +02:00
proxy - > priv - > signals_subscription_id ) ;
2010-05-06 20:13:59 +02:00
2011-03-14 19:54:46 +01:00
if ( proxy - > priv - > connection ! = NULL )
g_object_unref ( proxy - > priv - > connection ) ;
2010-06-11 21:45:18 +02:00
g_free ( proxy - > priv - > name ) ;
g_free ( proxy - > priv - > name_owner ) ;
2010-05-06 20:13:59 +02:00
g_free ( proxy - > priv - > object_path ) ;
g_free ( proxy - > priv - > interface_name ) ;
if ( proxy - > priv - > properties ! = NULL )
g_hash_table_unref ( proxy - > priv - > properties ) ;
if ( proxy - > priv - > expected_interface ! = NULL )
2011-03-28 17:34:48 +02:00
{
g_dbus_interface_info_cache_release ( proxy - > priv - > expected_interface ) ;
g_dbus_interface_info_unref ( proxy - > priv - > expected_interface ) ;
}
2010-05-06 20:13:59 +02:00
2011-04-08 22:12:33 +02:00
if ( proxy - > priv - > object ! = NULL )
g_object_remove_weak_pointer ( G_OBJECT ( proxy - > priv - > object ) , ( gpointer * ) & proxy - > priv - > object ) ;
2010-05-10 04:13:18 +02:00
G_OBJECT_CLASS ( g_dbus_proxy_parent_class ) - > finalize ( object ) ;
2010-05-06 20:13:59 +02:00
}
static void
g_dbus_proxy_get_property ( GObject * object ,
guint prop_id ,
GValue * value ,
GParamSpec * pspec )
{
GDBusProxy * proxy = G_DBUS_PROXY ( object ) ;
switch ( prop_id )
{
case PROP_G_CONNECTION :
g_value_set_object ( value , proxy - > priv - > connection ) ;
break ;
case PROP_G_FLAGS :
g_value_set_flags ( value , proxy - > priv - > flags ) ;
break ;
2010-06-11 21:45:18 +02:00
case PROP_G_NAME :
g_value_set_string ( value , proxy - > priv - > name ) ;
break ;
case PROP_G_NAME_OWNER :
2011-08-08 19:22:42 +02:00
g_value_take_string ( value , g_dbus_proxy_get_name_owner ( proxy ) ) ;
2010-05-06 20:13:59 +02:00
break ;
case PROP_G_OBJECT_PATH :
g_value_set_string ( value , proxy - > priv - > object_path ) ;
break ;
case PROP_G_INTERFACE_NAME :
g_value_set_string ( value , proxy - > priv - > interface_name ) ;
break ;
case PROP_G_DEFAULT_TIMEOUT :
2011-08-08 19:22:42 +02:00
g_value_set_int ( value , g_dbus_proxy_get_default_timeout ( proxy ) ) ;
2010-05-06 20:13:59 +02:00
break ;
case PROP_G_INTERFACE_INFO :
g_value_set_boxed ( value , g_dbus_proxy_get_interface_info ( proxy ) ) ;
break ;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , prop_id , pspec ) ;
break ;
}
}
static void
g_dbus_proxy_set_property ( GObject * object ,
guint prop_id ,
const GValue * value ,
GParamSpec * pspec )
{
GDBusProxy * proxy = G_DBUS_PROXY ( object ) ;
switch ( prop_id )
{
case PROP_G_CONNECTION :
proxy - > priv - > connection = g_value_dup_object ( value ) ;
break ;
case PROP_G_FLAGS :
proxy - > priv - > flags = g_value_get_flags ( value ) ;
break ;
2010-06-11 21:45:18 +02:00
case PROP_G_NAME :
proxy - > priv - > name = g_value_dup_string ( value ) ;
2010-05-06 20:13:59 +02:00
break ;
case PROP_G_OBJECT_PATH :
proxy - > priv - > object_path = g_value_dup_string ( value ) ;
break ;
case PROP_G_INTERFACE_NAME :
proxy - > priv - > interface_name = g_value_dup_string ( value ) ;
break ;
case PROP_G_DEFAULT_TIMEOUT :
g_dbus_proxy_set_default_timeout ( proxy , g_value_get_int ( value ) ) ;
break ;
case PROP_G_INTERFACE_INFO :
g_dbus_proxy_set_interface_info ( proxy , g_value_get_boxed ( value ) ) ;
break ;
2010-06-11 21:45:18 +02:00
case PROP_G_BUS_TYPE :
proxy - > priv - > bus_type = g_value_get_enum ( value ) ;
break ;
2010-05-06 20:13:59 +02:00
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , prop_id , pspec ) ;
break ;
}
}
static void
g_dbus_proxy_class_init ( GDBusProxyClass * klass )
{
GObjectClass * gobject_class = G_OBJECT_CLASS ( klass ) ;
2011-05-26 15:26:29 +02:00
gobject_class - > dispose = g_dbus_proxy_dispose ;
2010-05-06 20:13:59 +02:00
gobject_class - > finalize = g_dbus_proxy_finalize ;
gobject_class - > set_property = g_dbus_proxy_set_property ;
gobject_class - > get_property = g_dbus_proxy_get_property ;
/* Note that all property names are prefixed to avoid collisions with D-Bus property names
* in derived classes */
/**
* GDBusProxy : g - interface - info :
*
* Ensure that interactions with this proxy conform to the given
2011-10-04 17:37:16 +02:00
* interface . This is mainly to ensure that malformed data received
* from the other peer is ignored . The given # GDBusInterfaceInfo is
* said to be the < emphasis > expected interface < / emphasis > .
*
* The checks performed are :
* < itemizedlist >
* < listitem > < para >
* When completing a method call , if the type signature of
* the reply message isn ' t what ' s expected , the reply is
* discarded and the # GError is set to % G_IO_ERROR_INVALID_ARGUMENT .
* < / para > < / listitem >
* < listitem > < para >
* Received signals that have a type signature mismatch are dropped and
* a warning is logged via g_warning ( ) .
* < / para > < / listitem >
* < listitem > < para >
* Properties received via the initial < literal > GetAll ( ) < / literal > call
* or via the < literal > : : PropertiesChanged < / literal > signal ( on the
* < ulink url = " http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties " > org . freedesktop . DBus . Properties < / ulink > interface ) or
* set using g_dbus_proxy_set_cached_property ( ) with a type signature
* mismatch are ignored and a warning is logged via g_warning ( ) .
* < / para > < / listitem >
* < / itemizedlist >
* Note that these checks are never done on methods , signals and
* properties that are not referenced in the given
* # GDBusInterfaceInfo , since extending a D - Bus interface on the
* service - side is not considered an ABI break .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
g_object_class_install_property ( gobject_class ,
PROP_G_INTERFACE_INFO ,
g_param_spec_boxed ( " g-interface-info " ,
2010-05-10 04:13:18 +02:00
P_ ( " Interface Information " ) ,
P_ ( " Interface Information " ) ,
2010-05-06 20:13:59 +02:00
G_TYPE_DBUS_INTERFACE_INFO ,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
/**
* GDBusProxy : g - connection :
*
* The # GDBusConnection the proxy is for .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
g_object_class_install_property ( gobject_class ,
PROP_G_CONNECTION ,
g_param_spec_object ( " g-connection " ,
2010-05-10 04:13:18 +02:00
P_ ( " g-connection " ) ,
P_ ( " The connection the proxy is for " ) ,
2010-05-06 20:13:59 +02:00
G_TYPE_DBUS_CONNECTION ,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
2010-06-11 21:45:18 +02:00
/**
* GDBusProxy : g - bus - type :
*
* If this property is not % G_BUS_TYPE_NONE , then
* # GDBusProxy : g - connection must be % NULL and will be set to the
* # GDBusConnection obtained by calling g_bus_get ( ) with the value
* of this property .
*
* Since : 2.26
*/
g_object_class_install_property ( gobject_class ,
PROP_G_BUS_TYPE ,
g_param_spec_enum ( " g-bus-type " ,
P_ ( " Bus Type " ) ,
P_ ( " The bus to connect to, if any " ) ,
G_TYPE_BUS_TYPE ,
G_BUS_TYPE_NONE ,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
2010-05-06 20:13:59 +02:00
/**
* GDBusProxy : g - flags :
*
* Flags from the # GDBusProxyFlags enumeration .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
g_object_class_install_property ( gobject_class ,
PROP_G_FLAGS ,
g_param_spec_flags ( " g-flags " ,
2010-05-10 04:13:18 +02:00
P_ ( " g-flags " ) ,
P_ ( " Flags for the proxy " ) ,
2010-05-06 20:13:59 +02:00
G_TYPE_DBUS_PROXY_FLAGS ,
G_DBUS_PROXY_FLAGS_NONE ,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
/**
2010-06-11 21:45:18 +02:00
* GDBusProxy : g - name :
2010-05-06 20:13:59 +02:00
*
2010-06-11 21:45:18 +02:00
* The well - known or unique name that the proxy is for .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
g_object_class_install_property ( gobject_class ,
2010-06-11 21:45:18 +02:00
PROP_G_NAME ,
g_param_spec_string ( " g-name " ,
P_ ( " g-name " ) ,
P_ ( " The well-known or unique name that the proxy is for " ) ,
2010-05-06 20:13:59 +02:00
NULL ,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
2010-06-11 21:45:18 +02:00
/**
* GDBusProxy : g - name - owner :
*
2012-02-19 17:35:10 +01:00
* The unique name that owns # GDBusProxy : g - name or % NULL if no - one
2010-06-11 21:45:18 +02:00
* currently owns that name . You may connect to # GObject : : notify signal to
* track changes to this property .
*
* Since : 2.26
*/
g_object_class_install_property ( gobject_class ,
PROP_G_NAME_OWNER ,
g_param_spec_string ( " g-name-owner " ,
P_ ( " g-name-owner " ) ,
P_ ( " The unique name for the owner " ) ,
NULL ,
G_PARAM_READABLE |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
2010-05-06 20:13:59 +02:00
/**
* GDBusProxy : g - object - path :
*
* The object path the proxy is for .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
g_object_class_install_property ( gobject_class ,
PROP_G_OBJECT_PATH ,
g_param_spec_string ( " g-object-path " ,
2010-05-10 04:13:18 +02:00
P_ ( " g-object-path " ) ,
P_ ( " The object path the proxy is for " ) ,
2010-05-06 20:13:59 +02:00
NULL ,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
/**
* GDBusProxy : g - interface - name :
*
* The D - Bus interface name the proxy is for .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
g_object_class_install_property ( gobject_class ,
PROP_G_INTERFACE_NAME ,
g_param_spec_string ( " g-interface-name " ,
2010-05-10 04:13:18 +02:00
P_ ( " g-interface-name " ) ,
P_ ( " The D-Bus interface name the proxy is for " ) ,
2010-05-06 20:13:59 +02:00
NULL ,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
/**
* GDBusProxy : g - default - timeout :
*
* The timeout to use if - 1 ( specifying default timeout ) is passed
2010-05-10 17:47:08 +02:00
* as @ timeout_msec in the g_dbus_proxy_call ( ) and
* g_dbus_proxy_call_sync ( ) functions .
2010-05-06 20:13:59 +02:00
*
* This allows applications to set a proxy - wide timeout for all
* remote method invocations on the proxy . If this property is - 1 ,
* the default timeout ( typically 25 seconds ) is used . If set to
* % G_MAXINT , then no timeout is used .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
g_object_class_install_property ( gobject_class ,
PROP_G_DEFAULT_TIMEOUT ,
g_param_spec_int ( " g-default-timeout " ,
2010-05-10 04:13:18 +02:00
P_ ( " Default Timeout " ) ,
P_ ( " Timeout for remote method invocation " ) ,
2010-05-06 20:13:59 +02:00
- 1 ,
G_MAXINT ,
- 1 ,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK ) ) ;
/**
* GDBusProxy : : g - properties - changed :
* @ proxy : The # GDBusProxy emitting the signal .
2010-05-13 22:57:29 +02:00
* @ changed_properties : A # GVariant containing the properties that changed
* @ invalidated_properties : A % NULL terminated array of properties that was invalidated
2010-05-06 20:13:59 +02:00
*
2010-05-13 17:56:15 +02:00
* Emitted when one or more D - Bus properties on @ proxy changes . The
2010-05-13 22:57:29 +02:00
* local cache has already been updated when this signal fires . Note
* that both @ changed_properties and @ invalidated_properties are
* guaranteed to never be % NULL ( either may be empty though ) .
2010-05-13 17:56:15 +02:00
*
2012-02-08 18:46:04 +01:00
* If the proxy has the flag
* % G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES set , then
* @ invalidated_properties will always be empty .
*
2010-05-13 17:56:15 +02:00
* This signal corresponds to the
* < literal > PropertiesChanged < / literal > D - Bus signal on the
* < literal > org . freedesktop . DBus . Properties < / literal > interface .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
signals [ PROPERTIES_CHANGED_SIGNAL ] = g_signal_new ( " g-properties-changed " ,
G_TYPE_DBUS_PROXY ,
2011-03-04 18:21:51 +01:00
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT ,
2010-05-06 20:13:59 +02:00
G_STRUCT_OFFSET ( GDBusProxyClass , g_properties_changed ) ,
NULL ,
NULL ,
2011-07-19 19:18:10 +02:00
NULL ,
2010-05-06 20:13:59 +02:00
G_TYPE_NONE ,
2010-05-13 17:56:15 +02:00
2 ,
G_TYPE_VARIANT ,
2010-05-13 19:01:04 +02:00
G_TYPE_STRV | G_SIGNAL_TYPE_STATIC_SCOPE ) ;
2010-05-06 20:13:59 +02:00
/**
* GDBusProxy : : g - signal :
* @ proxy : The # GDBusProxy emitting the signal .
* @ sender_name : The sender of the signal or % NULL if the connection is not a bus connection .
* @ signal_name : The name of the signal .
* @ parameters : A # GVariant tuple with parameters for the signal .
*
* Emitted when a signal from the remote object and interface that @ proxy is for , has been received .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
signals [ SIGNAL_SIGNAL ] = g_signal_new ( " g-signal " ,
G_TYPE_DBUS_PROXY ,
2011-03-04 18:21:51 +01:00
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT ,
2010-05-06 20:13:59 +02:00
G_STRUCT_OFFSET ( GDBusProxyClass , g_signal ) ,
NULL ,
NULL ,
2011-07-19 19:18:10 +02:00
NULL ,
2010-05-06 20:13:59 +02:00
G_TYPE_NONE ,
3 ,
G_TYPE_STRING ,
G_TYPE_STRING ,
G_TYPE_VARIANT ) ;
g_type_class_add_private ( klass , sizeof ( GDBusProxyPrivate ) ) ;
}
static void
g_dbus_proxy_init ( GDBusProxy * proxy )
{
proxy - > priv = G_TYPE_INSTANCE_GET_PRIVATE ( proxy , G_TYPE_DBUS_PROXY , GDBusProxyPrivate ) ;
2011-05-26 15:26:29 +02:00
proxy - > priv - > signal_subscription_data = g_slice_new0 ( SignalSubscriptionData ) ;
proxy - > priv - > signal_subscription_data - > ref_count = 1 ;
proxy - > priv - > signal_subscription_data - > proxy = proxy ;
2010-05-13 23:10:15 +02:00
proxy - > priv - > properties = g_hash_table_new_full ( g_str_hash ,
g_str_equal ,
g_free ,
( GDestroyNotify ) g_variant_unref ) ;
2010-05-06 20:13:59 +02:00
}
/* ---------------------------------------------------------------------------------------------------- */
2010-07-30 22:33:29 +02:00
static gint
property_name_sort_func ( const gchar * * a ,
const gchar * * b )
{
return g_strcmp0 ( * a , * b ) ;
}
2010-05-06 20:13:59 +02:00
/**
* g_dbus_proxy_get_cached_property_names :
* @ proxy : A # GDBusProxy .
*
* Gets the names of all cached properties on @ proxy .
*
2011-08-11 11:36:22 +02:00
* Returns : ( transfer full ) : A % NULL - terminated array of strings or % NULL if
* @ proxy has no cached properties . Free the returned array with
* g_strfreev ( ) .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
gchar * *
2010-05-13 23:10:15 +02:00
g_dbus_proxy_get_cached_property_names ( GDBusProxy * proxy )
2010-05-06 20:13:59 +02:00
{
gchar * * names ;
GPtrArray * p ;
GHashTableIter iter ;
const gchar * key ;
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
2011-05-26 15:54:47 +02:00
G_LOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
names = NULL ;
2010-05-13 23:10:15 +02:00
if ( g_hash_table_size ( proxy - > priv - > properties ) = = 0 )
goto out ;
2010-05-06 20:13:59 +02:00
p = g_ptr_array_new ( ) ;
g_hash_table_iter_init ( & iter , proxy - > priv - > properties ) ;
while ( g_hash_table_iter_next ( & iter , ( gpointer ) & key , NULL ) )
2010-05-10 04:13:18 +02:00
g_ptr_array_add ( p , g_strdup ( key ) ) ;
2010-07-30 22:33:29 +02:00
g_ptr_array_sort ( p , ( GCompareFunc ) property_name_sort_func ) ;
2010-05-06 20:13:59 +02:00
g_ptr_array_add ( p , NULL ) ;
names = ( gchar * * ) g_ptr_array_free ( p , FALSE ) ;
out :
2011-05-26 15:54:47 +02:00
G_UNLOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
return names ;
}
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* properties_lock must be held for as long as you will keep the
* returned value
*/
2010-05-13 02:43:40 +02:00
static const GDBusPropertyInfo *
2011-10-04 17:37:16 +02:00
lookup_property_info ( GDBusProxy * proxy ,
const gchar * property_name )
2010-05-13 02:43:40 +02:00
{
2011-10-04 17:37:16 +02:00
const GDBusPropertyInfo * info = NULL ;
2010-05-13 02:43:40 +02:00
if ( proxy - > priv - > expected_interface = = NULL )
2011-10-04 17:37:16 +02:00
goto out ;
2010-05-13 02:43:40 +02:00
info = g_dbus_interface_info_lookup_property ( proxy - > priv - > expected_interface , property_name ) ;
2011-10-04 17:37:16 +02:00
out :
2010-05-13 02:43:40 +02:00
return info ;
}
2010-05-06 20:13:59 +02:00
/**
* g_dbus_proxy_get_cached_property :
* @ proxy : A # GDBusProxy .
* @ property_name : Property name .
*
2010-05-13 02:43:40 +02:00
* Looks up the value for a property from the cache . This call does no
* blocking IO .
2010-05-06 20:13:59 +02:00
*
2010-05-13 02:43:40 +02:00
* If @ proxy has an expected interface ( see
2011-10-04 17:37:16 +02:00
* # GDBusProxy : g - interface - info ) and @ property_name is referenced by
* it , then @ value is checked against the type of the property .
2010-05-06 20:13:59 +02:00
*
2010-05-13 02:43:40 +02:00
* Returns : A reference to the # GVariant instance that holds the value
* for @ property_name or % NULL if the value is not in the cache . The
* returned reference must be freed with g_variant_unref ( ) .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
GVariant *
2010-05-10 04:13:18 +02:00
g_dbus_proxy_get_cached_property ( GDBusProxy * proxy ,
2010-05-13 02:43:40 +02:00
const gchar * property_name )
2010-05-06 20:13:59 +02:00
{
2011-10-04 17:37:16 +02:00
const GDBusPropertyInfo * info ;
2010-05-06 20:13:59 +02:00
GVariant * value ;
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
g_return_val_if_fail ( property_name ! = NULL , NULL ) ;
2011-05-26 15:54:47 +02:00
G_LOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
value = g_hash_table_lookup ( proxy - > priv - > properties , property_name ) ;
if ( value = = NULL )
2011-10-04 17:37:16 +02:00
goto out ;
info = lookup_property_info ( proxy , property_name ) ;
if ( info ! = NULL )
2010-05-06 20:13:59 +02:00
{
2011-10-04 17:37:16 +02:00
const gchar * type_string = g_variant_get_type_string ( value ) ;
if ( g_strcmp0 ( type_string , info - > signature ) ! = 0 )
{
g_warning ( " Trying to get property %s with type %s but according to the expected "
" interface the type is %s " ,
property_name ,
type_string ,
info - > signature ) ;
value = NULL ;
goto out ;
}
2010-05-06 20:13:59 +02:00
}
g_variant_ref ( value ) ;
out :
2011-05-26 15:54:47 +02:00
G_UNLOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
return value ;
}
2010-05-13 02:43:40 +02:00
/**
* g_dbus_proxy_set_cached_property :
* @ proxy : A # GDBusProxy
* @ property_name : Property name .
2011-03-30 19:52:31 +02:00
* @ value : ( allow - none ) : Value for the property or % NULL to remove it from the cache .
2010-05-13 02:43:40 +02:00
*
* If @ value is not % NULL , sets the cached value for the property with
* name @ property_name to the value in @ value .
*
* If @ value is % NULL , then the cached value is removed from the
* property cache .
*
* If @ proxy has an expected interface ( see
2011-10-04 17:37:16 +02:00
* # GDBusProxy : g - interface - info ) and @ property_name is referenced by
* it , then @ value is checked against the type of the property .
2010-05-13 02:43:40 +02:00
*
* If the @ value # GVariant is floating , it is consumed . This allows
* convenient ' inline ' use of g_variant_new ( ) , e . g .
* | [
* g_dbus_proxy_set_cached_property ( proxy ,
* " SomeProperty " ,
* g_variant_new ( " (si) " ,
* " A String " ,
* 42 ) ) ;
* ] |
*
* Normally you will not need to use this method since @ proxy is
* tracking changes using the
* < literal > org . freedesktop . DBus . Properties . PropertiesChanged < / literal >
* D - Bus signal . However , for performance reasons an object may decide
* to not use this signal for some properties and instead use a
* proprietary out - of - band mechanism to transmit changes .
*
* As a concrete example , consider an object with a property
* < literal > ChatroomParticipants < / literal > which is an array of
* strings . Instead of transmitting the same ( long ) array every time
* the property changes , it is more efficient to only transmit the
* delta using e . g . signals < literal > ChatroomParticipantJoined ( String
* name ) < / literal > and < literal > ChatroomParticipantParted ( String
* name ) < / literal > .
*
* Since : 2.26
*/
void
g_dbus_proxy_set_cached_property ( GDBusProxy * proxy ,
const gchar * property_name ,
GVariant * value )
{
const GDBusPropertyInfo * info ;
g_return_if_fail ( G_IS_DBUS_PROXY ( proxy ) ) ;
g_return_if_fail ( property_name ! = NULL ) ;
2011-05-26 15:54:47 +02:00
G_LOCK ( properties_lock ) ;
2010-05-13 02:43:40 +02:00
if ( value ! = NULL )
{
2011-10-04 17:37:16 +02:00
info = lookup_property_info ( proxy , property_name ) ;
2010-05-13 02:43:40 +02:00
if ( info ! = NULL )
{
if ( g_strcmp0 ( info - > signature , g_variant_get_type_string ( value ) ) ! = 0 )
{
2011-04-29 16:59:42 +02:00
g_warning ( " Trying to set property %s of type %s but according to the expected "
" interface the type is %s " ,
2010-05-13 02:43:40 +02:00
property_name ,
g_variant_get_type_string ( value ) ,
info - > signature ) ;
goto out ;
}
}
g_hash_table_insert ( proxy - > priv - > properties ,
g_strdup ( property_name ) ,
g_variant_ref_sink ( value ) ) ;
}
else
{
g_hash_table_remove ( proxy - > priv - > properties , property_name ) ;
}
out :
2011-05-26 15:54:47 +02:00
G_UNLOCK ( properties_lock ) ;
2010-05-13 02:43:40 +02:00
}
2010-05-06 20:13:59 +02:00
/* ---------------------------------------------------------------------------------------------------- */
static void
2010-05-10 04:13:18 +02:00
on_signal_received ( GDBusConnection * connection ,
const gchar * sender_name ,
const gchar * object_path ,
const gchar * interface_name ,
const gchar * signal_name ,
GVariant * parameters ,
gpointer user_data )
2010-05-06 20:13:59 +02:00
{
2011-05-26 15:26:29 +02:00
SignalSubscriptionData * data = user_data ;
GDBusProxy * proxy ;
G_LOCK ( signal_subscription_lock ) ;
proxy = data - > proxy ;
if ( proxy = = NULL )
2011-05-26 16:07:38 +02:00
{
G_UNLOCK ( signal_subscription_lock ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
return ;
2011-05-26 16:07:38 +02:00
}
else
{
g_object_ref ( proxy ) ;
G_UNLOCK ( signal_subscription_lock ) ;
}
2010-05-06 20:13:59 +02:00
2010-05-13 23:20:39 +02:00
if ( ! proxy - > priv - > initialized )
goto out ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-07-14 17:14:58 +02:00
if ( proxy - > priv - > name_owner ! = NULL & & g_strcmp0 ( sender_name , proxy - > priv - > name_owner ) ! = 0 )
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
{
G_UNLOCK ( properties_lock ) ;
goto out ;
}
2010-06-11 21:45:18 +02:00
2011-03-28 18:10:25 +02:00
if ( proxy - > priv - > expected_interface ! = NULL )
{
const GDBusSignalInfo * info ;
info = g_dbus_interface_info_lookup_signal ( proxy - > priv - > expected_interface , signal_name ) ;
2011-10-04 17:37:16 +02:00
if ( info ! = NULL )
2011-03-28 19:04:34 +02:00
{
2011-10-04 17:37:16 +02:00
GVariantType * expected_type ;
expected_type = _g_dbus_compute_complete_signature ( info - > args ) ;
if ( ! g_variant_type_equal ( expected_type , g_variant_get_type ( parameters ) ) )
{
gchar * expected_type_string = g_variant_type_dup_string ( expected_type ) ;
g_warning ( " Dropping signal %s of type %s since the type from the expected interface is %s " ,
info - > name ,
g_variant_get_type_string ( parameters ) ,
expected_type_string ) ;
g_free ( expected_type_string ) ;
g_variant_type_free ( expected_type ) ;
G_UNLOCK ( properties_lock ) ;
goto out ;
}
2011-03-28 19:04:34 +02:00
g_variant_type_free ( expected_type ) ;
}
2011-03-28 18:10:25 +02:00
}
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
g_signal_emit ( proxy ,
signals [ SIGNAL_SIGNAL ] ,
0 ,
sender_name ,
signal_name ,
parameters ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
2010-05-13 23:20:39 +02:00
out :
2011-05-26 15:26:29 +02:00
if ( proxy ! = NULL )
g_object_unref ( proxy ) ;
2010-05-06 20:13:59 +02:00
}
/* ---------------------------------------------------------------------------------------------------- */
2011-05-26 15:54:47 +02:00
/* must hold properties_lock */
2011-02-19 02:34:06 +01:00
static void
insert_property_checked ( GDBusProxy * proxy ,
gchar * property_name ,
GVariant * value )
{
if ( proxy - > priv - > expected_interface ! = NULL )
{
const GDBusPropertyInfo * info ;
info = g_dbus_interface_info_lookup_property ( proxy - > priv - > expected_interface , property_name ) ;
2011-10-04 17:37:16 +02:00
/* Only check known properties */
if ( info ! = NULL )
{
/* Warn about properties with the wrong type */
if ( g_strcmp0 ( info - > signature , g_variant_get_type_string ( value ) ) ! = 0 )
{
g_warning ( " Received property %s with type %s does not match expected type "
" %s in the expected interface " ,
property_name ,
g_variant_get_type_string ( value ) ,
info - > signature ) ;
goto invalid ;
}
}
2011-02-19 02:34:06 +01:00
}
g_hash_table_insert ( proxy - > priv - > properties ,
property_name , /* adopts string */
value ) ; /* adopts value */
return ;
invalid :
g_variant_unref ( value ) ;
g_free ( property_name ) ;
}
2012-02-08 18:46:04 +01:00
typedef struct
{
GDBusProxy * proxy ;
gchar * prop_name ;
} InvalidatedPropGetData ;
static void
invalidated_property_get_cb ( GDBusConnection * connection ,
GAsyncResult * res ,
gpointer user_data )
{
InvalidatedPropGetData * data = user_data ;
const gchar * invalidated_properties [ ] = { NULL } ;
GVariantBuilder builder ;
GVariant * value = NULL ;
GVariant * unpacked_value = NULL ;
/* errors are fine, the other end could have disconnected */
value = g_dbus_connection_call_finish ( connection , res , NULL ) ;
if ( value = = NULL )
{
goto out ;
}
if ( ! g_variant_is_of_type ( value , G_VARIANT_TYPE ( " (v) " ) ) )
{
g_warning ( " Expected type `(v)' for Get() reply, got `%s' " , g_variant_get_type_string ( value ) ) ;
goto out ;
}
g_variant_get ( value , " (v) " , & unpacked_value ) ;
/* synthesize the a{sv} in the PropertiesChanged signal */
g_variant_builder_init ( & builder , G_VARIANT_TYPE ( " a{sv} " ) ) ;
g_variant_builder_add ( & builder , " {sv} " , data - > prop_name , unpacked_value ) ;
G_LOCK ( properties_lock ) ;
insert_property_checked ( data - > proxy ,
data - > prop_name , /* adopts string */
unpacked_value ) ; /* adopts value */
data - > prop_name = NULL ;
G_UNLOCK ( properties_lock ) ;
g_signal_emit ( data - > proxy ,
signals [ PROPERTIES_CHANGED_SIGNAL ] , 0 ,
g_variant_builder_end ( & builder ) , /* consumed */
invalidated_properties ) ;
out :
if ( value ! = NULL )
g_variant_unref ( value ) ;
g_object_unref ( data - > proxy ) ;
g_free ( data - > prop_name ) ;
g_slice_free ( InvalidatedPropGetData , data ) ;
}
2010-05-06 20:13:59 +02:00
static void
2010-05-10 04:13:18 +02:00
on_properties_changed ( GDBusConnection * connection ,
const gchar * sender_name ,
const gchar * object_path ,
const gchar * interface_name ,
const gchar * signal_name ,
GVariant * parameters ,
gpointer user_data )
2010-05-06 20:13:59 +02:00
{
2011-05-26 15:26:29 +02:00
SignalSubscriptionData * data = user_data ;
2012-02-08 18:46:04 +01:00
gboolean emit_g_signal = FALSE ;
2011-05-26 15:26:29 +02:00
GDBusProxy * proxy ;
2010-05-06 20:13:59 +02:00
const gchar * interface_name_for_signal ;
2010-05-10 19:31:54 +02:00
GVariant * changed_properties ;
2010-05-13 17:56:15 +02:00
gchar * * invalidated_properties ;
2010-05-13 19:01:04 +02:00
GVariantIter iter ;
gchar * key ;
GVariant * value ;
2010-05-14 18:55:25 +02:00
guint n ;
2010-05-06 20:13:59 +02:00
2011-08-13 22:09:41 +02:00
changed_properties = NULL ;
invalidated_properties = NULL ;
2011-05-26 15:26:29 +02:00
G_LOCK ( signal_subscription_lock ) ;
proxy = data - > proxy ;
if ( proxy = = NULL )
2011-05-26 16:07:38 +02:00
{
G_UNLOCK ( signal_subscription_lock ) ;
goto out ;
}
else
{
g_object_ref ( proxy ) ;
G_UNLOCK ( signal_subscription_lock ) ;
}
2011-05-26 15:26:29 +02:00
2010-05-13 23:20:39 +02:00
if ( ! proxy - > priv - > initialized )
goto out ;
2010-05-06 20:13:59 +02:00
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-07-14 17:14:58 +02:00
if ( proxy - > priv - > name_owner ! = NULL & & g_strcmp0 ( sender_name , proxy - > priv - > name_owner ) ! = 0 )
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
{
G_UNLOCK ( properties_lock ) ;
goto out ;
}
2010-06-11 21:45:18 +02:00
2010-05-13 19:01:04 +02:00
if ( ! g_variant_is_of_type ( parameters , G_VARIANT_TYPE ( " (sa{sv}as) " ) ) )
2010-05-06 20:13:59 +02:00
{
2010-05-13 17:56:15 +02:00
g_warning ( " Value for PropertiesChanged signal with type `%s' does not match `(sa{sv}as)' " ,
2010-05-06 20:13:59 +02:00
g_variant_get_type_string ( parameters ) ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-05-13 23:20:39 +02:00
goto out ;
2010-05-06 20:13:59 +02:00
}
g_variant_get ( parameters ,
2010-05-13 19:01:04 +02:00
" (&s@a{sv}^a&s) " ,
2010-05-06 20:13:59 +02:00
& interface_name_for_signal ,
2010-05-13 19:01:04 +02:00
& changed_properties ,
& invalidated_properties ) ;
2010-05-06 20:13:59 +02:00
if ( g_strcmp0 ( interface_name_for_signal , proxy - > priv - > interface_name ) ! = 0 )
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
{
G_UNLOCK ( properties_lock ) ;
goto out ;
}
2011-05-26 15:54:47 +02:00
2010-05-13 19:01:04 +02:00
g_variant_iter_init ( & iter , changed_properties ) ;
while ( g_variant_iter_next ( & iter , " {sv} " , & key , & value ) )
2010-05-06 20:13:59 +02:00
{
2011-02-19 02:34:06 +01:00
insert_property_checked ( proxy ,
key , /* adopts string */
value ) ; /* adopts value */
2012-02-08 18:46:04 +01:00
emit_g_signal = TRUE ;
2010-05-06 20:13:59 +02:00
}
2012-02-08 18:46:04 +01:00
if ( proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES )
{
if ( proxy - > priv - > name_owner ! = NULL )
{
for ( n = 0 ; invalidated_properties [ n ] ! = NULL ; n + + )
{
InvalidatedPropGetData * data ;
data = g_slice_new0 ( InvalidatedPropGetData ) ;
data - > proxy = g_object_ref ( proxy ) ;
data - > prop_name = g_strdup ( invalidated_properties [ n ] ) ;
g_dbus_connection_call ( proxy - > priv - > connection ,
proxy - > priv - > name_owner ,
proxy - > priv - > object_path ,
" org.freedesktop.DBus.Properties " ,
" Get " ,
g_variant_new ( " (ss) " , proxy - > priv - > interface_name , data - > prop_name ) ,
G_VARIANT_TYPE ( " (v) " ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 , /* timeout */
NULL , /* GCancellable */
( GAsyncReadyCallback ) invalidated_property_get_cb ,
data ) ;
}
}
}
else
2010-05-14 18:55:25 +02:00
{
2012-02-08 18:46:04 +01:00
emit_g_signal = TRUE ;
for ( n = 0 ; invalidated_properties [ n ] ! = NULL ; n + + )
{
g_hash_table_remove ( proxy - > priv - > properties , invalidated_properties [ n ] ) ;
}
2010-05-14 18:55:25 +02:00
}
2011-05-26 15:54:47 +02:00
G_UNLOCK ( properties_lock ) ;
2012-02-08 18:46:04 +01:00
if ( emit_g_signal )
{
g_signal_emit ( proxy , signals [ PROPERTIES_CHANGED_SIGNAL ] ,
0 ,
changed_properties ,
invalidated_properties ) ;
}
2010-05-06 20:13:59 +02:00
out :
2010-05-13 23:20:39 +02:00
if ( changed_properties ! = NULL )
g_variant_unref ( changed_properties ) ;
2010-05-13 19:01:04 +02:00
g_free ( invalidated_properties ) ;
2011-05-26 15:26:29 +02:00
if ( proxy ! = NULL )
g_object_unref ( proxy ) ;
2010-05-06 20:13:59 +02:00
}
/* ---------------------------------------------------------------------------------------------------- */
static void
process_get_all_reply ( GDBusProxy * proxy ,
GVariant * result )
{
2010-05-15 00:08:29 +02:00
GVariantIter * iter ;
gchar * key ;
GVariant * value ;
2011-05-26 15:54:47 +02:00
guint num_properties ;
2010-05-06 20:13:59 +02:00
2010-07-07 15:50:44 +02:00
if ( ! g_variant_is_of_type ( result , G_VARIANT_TYPE ( " (a{sv}) " ) ) )
2010-05-06 20:13:59 +02:00
{
g_warning ( " Value for GetAll reply with type `%s' does not match `(a{sv})' " ,
g_variant_get_type_string ( result ) ) ;
goto out ;
}
2011-05-26 15:54:47 +02:00
G_LOCK ( properties_lock ) ;
2010-05-15 00:08:29 +02:00
g_variant_get ( result , " (a{sv}) " , & iter ) ;
while ( g_variant_iter_next ( iter , " {sv} " , & key , & value ) )
2010-05-06 20:13:59 +02:00
{
2011-02-19 02:34:06 +01:00
insert_property_checked ( proxy ,
key , /* adopts string */
value ) ; /* adopts value */
2010-05-06 20:13:59 +02:00
}
2010-05-15 00:08:29 +02:00
g_variant_iter_free ( iter ) ;
2011-05-26 15:54:47 +02:00
num_properties = g_hash_table_size ( proxy - > priv - > properties ) ;
G_UNLOCK ( properties_lock ) ;
2010-07-07 15:50:44 +02:00
/* Synthesize ::g-properties-changed changed */
2011-05-26 15:54:47 +02:00
if ( num_properties > 0 )
2010-07-07 15:50:44 +02:00
{
GVariant * changed_properties ;
const gchar * invalidated_properties [ 1 ] = { NULL } ;
g_variant_get ( result ,
" (@a{sv}) " ,
& changed_properties ) ;
g_signal_emit ( proxy , signals [ PROPERTIES_CHANGED_SIGNAL ] ,
0 ,
changed_properties ,
invalidated_properties ) ;
g_variant_unref ( changed_properties ) ;
}
2010-05-06 20:13:59 +02:00
out :
;
}
2010-06-11 21:45:18 +02:00
typedef struct
2010-05-06 20:13:59 +02:00
{
2010-06-11 21:45:18 +02:00
GDBusProxy * proxy ;
GCancellable * cancellable ;
gchar * name_owner ;
} LoadPropertiesOnNameOwnerChangedData ;
static void
on_name_owner_changed_get_all_cb ( GDBusConnection * connection ,
GAsyncResult * res ,
gpointer user_data )
{
LoadPropertiesOnNameOwnerChangedData * data = user_data ;
2010-05-06 20:13:59 +02:00
GVariant * result ;
2010-06-11 21:45:18 +02:00
GError * error ;
gboolean cancelled ;
2010-05-06 20:13:59 +02:00
2010-06-11 21:45:18 +02:00
cancelled = FALSE ;
2010-05-06 20:13:59 +02:00
2010-06-11 21:45:18 +02:00
error = NULL ;
result = g_dbus_connection_call_finish ( connection ,
res ,
& error ) ;
if ( result = = NULL )
{
if ( error - > domain = = G_IO_ERROR & & error - > code = = G_IO_ERROR_CANCELLED )
cancelled = TRUE ;
/* We just ignore if GetAll() is failing. Because this might happen
* if the object has no properties at all . Or if the caller is
* not authorized to see the properties .
*
* Either way , apps can know about this by using
* get_cached_property_names ( ) or get_cached_property ( ) .
*
* TODO : handle G_DBUS_DEBUG flag ' proxy ' and , if enabled , log the
* fact that GetAll ( ) failed
*/
//g_debug ("error: %d %d %s", error->domain, error->code, error->message);
g_error_free ( error ) ;
}
2010-05-13 23:20:39 +02:00
2010-06-11 21:45:18 +02:00
/* and finally we can notify */
if ( ! cancelled )
2010-05-06 20:13:59 +02:00
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-06-11 21:45:18 +02:00
g_free ( data - > proxy - > priv - > name_owner ) ;
data - > proxy - > priv - > name_owner = data - > name_owner ;
data - > name_owner = NULL ; /* to avoid an extra copy, we steal the string */
g_hash_table_remove_all ( data - > proxy - > priv - > properties ) ;
2011-05-26 15:54:47 +02:00
G_UNLOCK ( properties_lock ) ;
2010-06-11 21:45:18 +02:00
if ( result ! = NULL )
2010-06-09 16:56:35 +02:00
{
2010-06-11 21:45:18 +02:00
process_get_all_reply ( data - > proxy , result ) ;
g_variant_unref ( result ) ;
2010-06-09 16:56:35 +02:00
}
2010-05-06 20:13:59 +02:00
2010-06-11 21:45:18 +02:00
g_object_notify ( G_OBJECT ( data - > proxy ) , " g-name-owner " ) ;
2010-05-06 20:13:59 +02:00
}
2010-06-11 21:45:18 +02:00
if ( data - > cancellable = = data - > proxy - > priv - > get_all_cancellable )
data - > proxy - > priv - > get_all_cancellable = NULL ;
2010-05-06 20:13:59 +02:00
2010-06-11 21:45:18 +02:00
g_object_unref ( data - > proxy ) ;
g_object_unref ( data - > cancellable ) ;
g_free ( data - > name_owner ) ;
g_free ( data ) ;
2010-05-06 20:13:59 +02:00
}
static void
2010-06-11 21:45:18 +02:00
on_name_owner_changed ( GDBusConnection * connection ,
const gchar * sender_name ,
const gchar * object_path ,
const gchar * interface_name ,
const gchar * signal_name ,
GVariant * parameters ,
gpointer user_data )
2010-05-06 20:13:59 +02:00
{
2011-05-26 15:26:29 +02:00
SignalSubscriptionData * data = user_data ;
GDBusProxy * proxy ;
2010-06-11 21:45:18 +02:00
const gchar * old_owner ;
const gchar * new_owner ;
2011-05-26 15:26:29 +02:00
G_LOCK ( signal_subscription_lock ) ;
proxy = data - > proxy ;
if ( proxy = = NULL )
2011-05-26 16:07:38 +02:00
{
G_UNLOCK ( signal_subscription_lock ) ;
goto out ;
}
else
{
g_object_ref ( proxy ) ;
G_UNLOCK ( signal_subscription_lock ) ;
}
2011-05-26 15:26:29 +02:00
2010-06-11 21:45:18 +02:00
/* if we are already trying to load properties, cancel that */
if ( proxy - > priv - > get_all_cancellable ! = NULL )
{
g_cancellable_cancel ( proxy - > priv - > get_all_cancellable ) ;
proxy - > priv - > get_all_cancellable = NULL ;
}
g_variant_get ( parameters ,
" (&s&s&s) " ,
2010-07-07 15:05:42 +02:00
NULL ,
2010-06-11 21:45:18 +02:00
& old_owner ,
& new_owner ) ;
if ( strlen ( new_owner ) = = 0 )
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-06-11 21:45:18 +02:00
g_free ( proxy - > priv - > name_owner ) ;
proxy - > priv - > name_owner = NULL ;
2010-07-07 15:50:44 +02:00
/* Synthesize ::g-properties-changed changed */
if ( ! ( proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES ) & &
g_hash_table_size ( proxy - > priv - > properties ) > 0 )
{
GVariantBuilder builder ;
GPtrArray * invalidated_properties ;
GHashTableIter iter ;
const gchar * key ;
/* Build changed_properties (always empty) and invalidated_properties ... */
g_variant_builder_init ( & builder , G_VARIANT_TYPE ( " a{sv} " ) ) ;
2011-03-04 18:21:51 +01:00
2010-07-07 15:50:44 +02:00
invalidated_properties = g_ptr_array_new_with_free_func ( g_free ) ;
g_hash_table_iter_init ( & iter , proxy - > priv - > properties ) ;
while ( g_hash_table_iter_next ( & iter , ( gpointer ) & key , NULL ) )
g_ptr_array_add ( invalidated_properties , g_strdup ( key ) ) ;
g_ptr_array_add ( invalidated_properties , NULL ) ;
/* ... throw out the properties ... */
g_hash_table_remove_all ( proxy - > priv - > properties ) ;
2011-05-26 15:54:47 +02:00
G_UNLOCK ( properties_lock ) ;
2010-07-07 15:50:44 +02:00
/* ... and finally emit the ::g-properties-changed signal */
g_signal_emit ( proxy , signals [ PROPERTIES_CHANGED_SIGNAL ] ,
0 ,
2011-03-04 18:21:51 +01:00
g_variant_builder_end ( & builder ) /* consumed */ ,
2010-07-07 15:50:44 +02:00
( const gchar * const * ) invalidated_properties - > pdata ) ;
g_ptr_array_unref ( invalidated_properties ) ;
}
2011-05-26 15:54:47 +02:00
else
{
G_UNLOCK ( properties_lock ) ;
}
2010-06-11 21:45:18 +02:00
g_object_notify ( G_OBJECT ( proxy ) , " g-name-owner " ) ;
}
else
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-06-11 21:45:18 +02:00
/* ignore duplicates - this can happen when activating the service */
if ( g_strcmp0 ( new_owner , proxy - > priv - > name_owner ) = = 0 )
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
{
G_UNLOCK ( properties_lock ) ;
goto out ;
}
2010-06-11 21:45:18 +02:00
if ( proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES )
{
g_free ( proxy - > priv - > name_owner ) ;
proxy - > priv - > name_owner = g_strdup ( new_owner ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
2010-06-11 21:45:18 +02:00
g_hash_table_remove_all ( proxy - > priv - > properties ) ;
2011-05-26 15:54:47 +02:00
G_UNLOCK ( properties_lock ) ;
2010-06-11 21:45:18 +02:00
g_object_notify ( G_OBJECT ( proxy ) , " g-name-owner " ) ;
}
else
{
LoadPropertiesOnNameOwnerChangedData * data ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-06-11 21:45:18 +02:00
/* start loading properties.. only then emit notify::g-name-owner .. we
* need to be able to cancel this in the event another NameOwnerChanged
* signal suddenly happens
*/
g_assert ( proxy - > priv - > get_all_cancellable = = NULL ) ;
proxy - > priv - > get_all_cancellable = g_cancellable_new ( ) ;
data = g_new0 ( LoadPropertiesOnNameOwnerChangedData , 1 ) ;
data - > proxy = g_object_ref ( proxy ) ;
data - > cancellable = proxy - > priv - > get_all_cancellable ;
data - > name_owner = g_strdup ( new_owner ) ;
g_dbus_connection_call ( proxy - > priv - > connection ,
data - > name_owner ,
proxy - > priv - > object_path ,
" org.freedesktop.DBus.Properties " ,
" GetAll " ,
g_variant_new ( " (s) " , proxy - > priv - > interface_name ) ,
G_VARIANT_TYPE ( " (a{sv}) " ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 , /* timeout */
proxy - > priv - > get_all_cancellable ,
( GAsyncReadyCallback ) on_name_owner_changed_get_all_cb ,
data ) ;
}
}
out :
2011-05-26 15:26:29 +02:00
if ( proxy ! = NULL )
g_object_unref ( proxy ) ;
2010-05-06 20:13:59 +02:00
}
/* ---------------------------------------------------------------------------------------------------- */
2010-06-11 21:45:18 +02:00
typedef struct
{
GDBusProxy * proxy ;
GCancellable * cancellable ;
GSimpleAsyncResult * simple ;
} AsyncInitData ;
2010-05-06 20:13:59 +02:00
static void
2010-06-11 21:45:18 +02:00
async_init_data_free ( AsyncInitData * data )
2010-05-06 20:13:59 +02:00
{
2010-06-11 21:45:18 +02:00
g_object_unref ( data - > proxy ) ;
if ( data - > cancellable ! = NULL )
g_object_unref ( data - > cancellable ) ;
g_object_unref ( data - > simple ) ;
g_free ( data ) ;
}
static void
async_init_get_all_cb ( GDBusConnection * connection ,
GAsyncResult * res ,
gpointer user_data )
{
AsyncInitData * data = user_data ;
2010-05-06 20:13:59 +02:00
GVariant * result ;
GError * error ;
error = NULL ;
2010-05-10 17:47:08 +02:00
result = g_dbus_connection_call_finish ( connection ,
res ,
& error ) ;
2010-05-06 20:13:59 +02:00
if ( result = = NULL )
{
2010-06-09 16:56:35 +02:00
/* We just ignore if GetAll() is failing. Because this might happen
* if the object has no properties at all . Or if the caller is
* not authorized to see the properties .
*
* Either way , apps can know about this by using
* get_cached_property_names ( ) or get_cached_property ( ) .
*
* TODO : handle G_DBUS_DEBUG flag ' proxy ' and , if enabled , log the
* fact that GetAll ( ) failed
*/
//g_debug ("error: %d %d %s", error->domain, error->code, error->message);
2010-05-06 20:13:59 +02:00
g_error_free ( error ) ;
}
else
{
2010-06-11 21:45:18 +02:00
g_simple_async_result_set_op_res_gpointer ( data - > simple ,
2010-05-06 20:13:59 +02:00
result ,
( GDestroyNotify ) g_variant_unref ) ;
}
2010-06-11 21:45:18 +02:00
g_simple_async_result_complete_in_idle ( data - > simple ) ;
async_init_data_free ( data ) ;
2010-05-06 20:13:59 +02:00
}
static void
2011-08-08 19:29:20 +02:00
async_init_data_set_name_owner ( AsyncInitData * data ,
const gchar * name_owner )
2010-05-06 20:13:59 +02:00
{
2011-08-15 16:57:59 +02:00
gboolean get_all ;
2010-05-06 20:13:59 +02:00
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
2011-08-08 19:29:20 +02:00
if ( name_owner ! = NULL )
2010-06-11 21:45:18 +02:00
{
2011-08-08 19:29:20 +02:00
/* it starts as NULL anyway */
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2011-08-08 19:29:20 +02:00
data - > proxy - > priv - > name_owner = g_strdup ( name_owner ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-06-11 21:45:18 +02:00
}
2010-05-13 23:20:39 +02:00
2011-08-15 16:57:59 +02:00
get_all = TRUE ;
if ( data - > proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES )
{
/* Don't load properties if the API user doesn't want them */
get_all = FALSE ;
}
2011-08-08 19:29:20 +02:00
else if ( name_owner = = NULL & & data - > proxy - > priv - > name ! = NULL )
2011-08-15 16:57:59 +02:00
{
/* Don't attempt to load properties if the name_owner is NULL (which
* usually means the name isn ' t owned ) , unless name is also NULL ( which
* means we actually wanted to talk to the directly - connected process -
* either dbus - daemon or a peer - instead of going via dbus - daemon )
*/
get_all = FALSE ;
}
if ( get_all )
2010-05-06 20:13:59 +02:00
{
/* load all properties asynchronously */
2010-06-11 21:45:18 +02:00
g_dbus_connection_call ( data - > proxy - > priv - > connection ,
2011-08-08 19:29:20 +02:00
name_owner ,
2010-06-11 21:45:18 +02:00
data - > proxy - > priv - > object_path ,
2010-05-10 17:47:08 +02:00
" org.freedesktop.DBus.Properties " ,
" GetAll " ,
2010-06-11 21:45:18 +02:00
g_variant_new ( " (s) " , data - > proxy - > priv - > interface_name ) ,
2010-05-24 22:46:24 +02:00
G_VARIANT_TYPE ( " (a{sv}) " ) ,
2010-05-10 17:47:08 +02:00
G_DBUS_CALL_FLAGS_NONE ,
- 1 , /* timeout */
2010-06-11 21:45:18 +02:00
data - > cancellable ,
( GAsyncReadyCallback ) async_init_get_all_cb ,
data ) ;
2010-05-06 20:13:59 +02:00
}
else
{
2010-06-11 21:45:18 +02:00
g_simple_async_result_complete_in_idle ( data - > simple ) ;
async_init_data_free ( data ) ;
}
2011-08-08 19:29:20 +02:00
}
2010-06-11 21:45:18 +02:00
2011-08-08 19:29:20 +02:00
static void
async_init_get_name_owner_cb ( GDBusConnection * connection ,
GAsyncResult * res ,
gpointer user_data )
{
AsyncInitData * data = user_data ;
GError * error ;
GVariant * result ;
error = NULL ;
result = g_dbus_connection_call_finish ( connection ,
res ,
& error ) ;
if ( result = = NULL )
{
if ( error - > domain = = G_DBUS_ERROR & &
error - > code = = G_DBUS_ERROR_NAME_HAS_NO_OWNER )
{
g_error_free ( error ) ;
async_init_data_set_name_owner ( data , NULL ) ;
}
else
{
g_simple_async_result_take_error ( data - > simple , error ) ;
g_simple_async_result_complete_in_idle ( data - > simple ) ;
async_init_data_free ( data ) ;
}
}
else
{
/* borrowed from result to avoid an extra copy */
const gchar * name_owner ;
g_variant_get ( result , " (&s) " , & name_owner ) ;
async_init_data_set_name_owner ( data , name_owner ) ;
g_variant_unref ( result ) ;
}
2010-06-11 21:45:18 +02:00
}
static void
async_init_call_get_name_owner ( AsyncInitData * data )
{
g_dbus_connection_call ( data - > proxy - > priv - > connection ,
" org.freedesktop.DBus " , /* name */
" /org/freedesktop/DBus " , /* object path */
" org.freedesktop.DBus " , /* interface */
" GetNameOwner " ,
g_variant_new ( " (s) " ,
data - > proxy - > priv - > name ) ,
G_VARIANT_TYPE ( " (s) " ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 , /* timeout */
data - > cancellable ,
( GAsyncReadyCallback ) async_init_get_name_owner_cb ,
data ) ;
}
static void
async_init_start_service_by_name_cb ( GDBusConnection * connection ,
GAsyncResult * res ,
gpointer user_data )
{
AsyncInitData * data = user_data ;
GError * error ;
GVariant * result ;
error = NULL ;
result = g_dbus_connection_call_finish ( connection ,
res ,
& error ) ;
if ( result = = NULL )
{
/* Errors are not unexpected; the bus will reply e.g.
*
* org . freedesktop . DBus . Error . ServiceUnknown : The name org . gnome . Epiphany2
* was not provided by any . service files
*
* This doesn ' t mean that the name doesn ' t have an owner , just
* that it ' s not provided by a . service file . So just proceed to
* invoke GetNameOwner ( ) if dealing with that error .
*/
if ( error - > domain = = G_DBUS_ERROR & &
error - > code = = G_DBUS_ERROR_SERVICE_UNKNOWN )
{
g_error_free ( error ) ;
}
else
{
g_prefix_error ( & error ,
_ ( " Error calling StartServiceByName for %s: " ) ,
data - > proxy - > priv - > name ) ;
goto failed ;
}
}
else
{
guint32 start_service_result ;
g_variant_get ( result ,
" (u) " ,
& start_service_result ) ;
g_variant_unref ( result ) ;
if ( start_service_result = = 1 | | /* DBUS_START_REPLY_SUCCESS */
start_service_result = = 2 ) /* DBUS_START_REPLY_ALREADY_RUNNING */
{
/* continue to invoke GetNameOwner() */
}
else
{
error = g_error_new ( G_IO_ERROR ,
G_IO_ERROR_FAILED ,
_ ( " Unexpected reply %d from StartServiceByName( \" %s \" ) method " ) ,
start_service_result ,
data - > proxy - > priv - > name ) ;
goto failed ;
}
}
async_init_call_get_name_owner ( data ) ;
return ;
failed :
g_warn_if_fail ( error ! = NULL ) ;
2010-09-23 13:02:50 +02:00
g_simple_async_result_take_error ( data - > simple , error ) ;
2010-06-11 21:45:18 +02:00
g_simple_async_result_complete_in_idle ( data - > simple ) ;
async_init_data_free ( data ) ;
}
static void
async_init_call_start_service_by_name ( AsyncInitData * data )
{
g_dbus_connection_call ( data - > proxy - > priv - > connection ,
" org.freedesktop.DBus " , /* name */
" /org/freedesktop/DBus " , /* object path */
" org.freedesktop.DBus " , /* interface */
" StartServiceByName " ,
g_variant_new ( " (su) " ,
data - > proxy - > priv - > name ,
0 ) ,
G_VARIANT_TYPE ( " (u) " ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 , /* timeout */
data - > cancellable ,
( GAsyncReadyCallback ) async_init_start_service_by_name_cb ,
data ) ;
}
static void
async_initable_init_second_async ( GAsyncInitable * initable ,
gint io_priority ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data )
{
GDBusProxy * proxy = G_DBUS_PROXY ( initable ) ;
AsyncInitData * data ;
data = g_new0 ( AsyncInitData , 1 ) ;
data - > proxy = g_object_ref ( proxy ) ;
data - > cancellable = cancellable ! = NULL ? g_object_ref ( cancellable ) : NULL ;
data - > simple = g_simple_async_result_new ( G_OBJECT ( proxy ) ,
callback ,
user_data ,
NULL ) ;
2012-03-13 21:41:57 +01:00
g_simple_async_result_set_check_cancellable ( data - > simple , cancellable ) ;
2010-06-11 21:45:18 +02:00
/* Check name ownership asynchronously - possibly also start the service */
if ( proxy - > priv - > name = = NULL )
{
/* Do nothing */
2011-08-08 19:29:20 +02:00
async_init_data_set_name_owner ( data , NULL ) ;
2010-06-11 21:45:18 +02:00
}
else if ( g_dbus_is_unique_name ( proxy - > priv - > name ) )
{
2011-08-08 19:29:20 +02:00
async_init_data_set_name_owner ( data , proxy - > priv - > name ) ;
2010-06-11 21:45:18 +02:00
}
else
{
if ( proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START )
{
async_init_call_get_name_owner ( data ) ;
}
else
{
async_init_call_start_service_by_name ( data ) ;
}
2010-05-06 20:13:59 +02:00
}
}
static gboolean
2010-06-11 21:45:18 +02:00
async_initable_init_second_finish ( GAsyncInitable * initable ,
GAsyncResult * res ,
GError * * error )
2010-05-06 20:13:59 +02:00
{
GDBusProxy * proxy = G_DBUS_PROXY ( initable ) ;
GSimpleAsyncResult * simple = G_SIMPLE_ASYNC_RESULT ( res ) ;
GVariant * result ;
gboolean ret ;
ret = FALSE ;
2010-06-09 16:56:35 +02:00
if ( g_simple_async_result_propagate_error ( simple , error ) )
goto out ;
2010-05-06 20:13:59 +02:00
result = g_simple_async_result_get_op_res_gpointer ( simple ) ;
2010-06-09 16:56:35 +02:00
if ( result ! = NULL )
2010-05-06 20:13:59 +02:00
{
process_get_all_reply ( proxy , result ) ;
}
ret = TRUE ;
out :
2010-05-13 23:20:39 +02:00
proxy - > priv - > initialized = TRUE ;
2010-05-06 20:13:59 +02:00
return ret ;
}
2010-06-11 21:45:18 +02:00
/* ---------------------------------------------------------------------------------------------------- */
static void
async_initable_init_first ( GAsyncInitable * initable )
{
GDBusProxy * proxy = G_DBUS_PROXY ( initable ) ;
if ( ! ( proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES ) )
{
/* subscribe to PropertiesChanged() */
2011-05-26 15:26:29 +02:00
proxy - > priv - > properties_changed_subscription_id =
2010-06-11 21:45:18 +02:00
g_dbus_connection_signal_subscribe ( proxy - > priv - > connection ,
proxy - > priv - > name ,
" org.freedesktop.DBus.Properties " ,
" PropertiesChanged " ,
proxy - > priv - > object_path ,
proxy - > priv - > interface_name ,
2010-07-19 21:03:00 +02:00
G_DBUS_SIGNAL_FLAGS_NONE ,
2010-06-11 21:45:18 +02:00
on_properties_changed ,
2011-05-26 15:26:29 +02:00
signal_subscription_ref ( proxy - > priv - > signal_subscription_data ) ,
( GDestroyNotify ) signal_subscription_unref ) ;
2010-06-11 21:45:18 +02:00
}
if ( ! ( proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS ) )
{
/* subscribe to all signals for the object */
2011-05-26 15:26:29 +02:00
proxy - > priv - > signals_subscription_id =
2010-06-11 21:45:18 +02:00
g_dbus_connection_signal_subscribe ( proxy - > priv - > connection ,
proxy - > priv - > name ,
proxy - > priv - > interface_name ,
NULL , /* member */
proxy - > priv - > object_path ,
NULL , /* arg0 */
2010-07-19 21:03:00 +02:00
G_DBUS_SIGNAL_FLAGS_NONE ,
2010-06-11 21:45:18 +02:00
on_signal_received ,
2011-05-26 15:26:29 +02:00
signal_subscription_ref ( proxy - > priv - > signal_subscription_data ) ,
( GDestroyNotify ) signal_subscription_unref ) ;
2010-06-11 21:45:18 +02:00
}
if ( proxy - > priv - > name ! = NULL & & ! g_dbus_is_unique_name ( proxy - > priv - > name ) )
{
proxy - > priv - > name_owner_changed_subscription_id =
g_dbus_connection_signal_subscribe ( proxy - > priv - > connection ,
" org.freedesktop.DBus " , /* name */
" org.freedesktop.DBus " , /* interface */
" NameOwnerChanged " , /* signal name */
" /org/freedesktop/DBus " , /* path */
proxy - > priv - > name , /* arg0 */
2010-07-19 21:03:00 +02:00
G_DBUS_SIGNAL_FLAGS_NONE ,
2010-06-11 21:45:18 +02:00
on_name_owner_changed ,
2011-05-26 15:26:29 +02:00
signal_subscription_ref ( proxy - > priv - > signal_subscription_data ) ,
( GDestroyNotify ) signal_subscription_unref ) ;
2010-06-11 21:45:18 +02:00
}
}
/* ---------------------------------------------------------------------------------------------------- */
/* initialization is split into two parts - the first is the
* non - blocing part that requires the callers GMainContext - the
* second is a blocking part async part that doesn ' t require the
* callers GMainContext . . we do this split so the code can be reused
* in the GInitable implementation below .
*
* Note that obtaining a GDBusConnection is not shared between the two
* paths .
*/
typedef struct
{
GDBusProxy * proxy ;
gint io_priority ;
GCancellable * cancellable ;
GAsyncReadyCallback callback ;
gpointer user_data ;
} GetConnectionData ;
static void
get_connection_cb ( GObject * source_object ,
GAsyncResult * res ,
gpointer user_data )
{
GetConnectionData * data = user_data ;
GError * error ;
2010-06-16 04:06:56 +02:00
error = NULL ;
2010-06-11 21:45:18 +02:00
data - > proxy - > priv - > connection = g_bus_get_finish ( res , & error ) ;
if ( data - > proxy - > priv - > connection = = NULL )
{
GSimpleAsyncResult * simple ;
simple = g_simple_async_result_new ( G_OBJECT ( data - > proxy ) ,
data - > callback ,
data - > user_data ,
NULL ) ;
2012-03-13 21:41:57 +01:00
g_simple_async_result_set_check_cancellable ( simple , data - > cancellable ) ;
2010-09-23 13:02:50 +02:00
g_simple_async_result_take_error ( simple , error ) ;
2010-06-11 21:45:18 +02:00
g_simple_async_result_complete_in_idle ( simple ) ;
g_object_unref ( simple ) ;
}
else
{
async_initable_init_first ( G_ASYNC_INITABLE ( data - > proxy ) ) ;
async_initable_init_second_async ( G_ASYNC_INITABLE ( data - > proxy ) ,
data - > io_priority ,
data - > cancellable ,
data - > callback ,
data - > user_data ) ;
}
if ( data - > cancellable ! = NULL )
g_object_unref ( data - > cancellable ) ;
2011-06-14 15:50:55 +02:00
g_object_unref ( data - > proxy ) ;
2010-06-11 21:45:18 +02:00
g_free ( data ) ;
}
static void
async_initable_init_async ( GAsyncInitable * initable ,
gint io_priority ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data )
{
GDBusProxy * proxy = G_DBUS_PROXY ( initable ) ;
if ( proxy - > priv - > bus_type ! = G_BUS_TYPE_NONE )
{
GetConnectionData * data ;
g_assert ( proxy - > priv - > connection = = NULL ) ;
data = g_new0 ( GetConnectionData , 1 ) ;
2010-06-17 18:26:15 +02:00
data - > proxy = g_object_ref ( proxy ) ;
2010-06-11 21:45:18 +02:00
data - > io_priority = io_priority ;
data - > cancellable = cancellable ! = NULL ? g_object_ref ( cancellable ) : NULL ;
data - > callback = callback ;
data - > user_data = user_data ;
g_bus_get ( proxy - > priv - > bus_type ,
cancellable ,
get_connection_cb ,
data ) ;
}
else
{
async_initable_init_first ( initable ) ;
async_initable_init_second_async ( initable , io_priority , cancellable , callback , user_data ) ;
}
}
static gboolean
async_initable_init_finish ( GAsyncInitable * initable ,
GAsyncResult * res ,
GError * * error )
{
return async_initable_init_second_finish ( initable , res , error ) ;
}
2010-05-06 20:13:59 +02:00
static void
async_initable_iface_init ( GAsyncInitableIface * async_initable_iface )
{
async_initable_iface - > init_async = async_initable_init_async ;
async_initable_iface - > init_finish = async_initable_init_finish ;
}
/* ---------------------------------------------------------------------------------------------------- */
2010-06-11 21:45:18 +02:00
typedef struct
{
GMainContext * context ;
GMainLoop * loop ;
GAsyncResult * res ;
} InitableAsyncInitableData ;
static void
async_initable_init_async_cb ( GObject * source_object ,
GAsyncResult * res ,
gpointer user_data )
{
InitableAsyncInitableData * data = user_data ;
data - > res = g_object_ref ( res ) ;
g_main_loop_quit ( data - > loop ) ;
}
/* Simply reuse the GAsyncInitable implementation but run the first
* part ( that is non - blocking and requires the callers GMainContext )
* with the callers GMainContext . . and the second with a private
* GMainContext ( bug 621310 is slightly related ) .
*
* Note that obtaining a GDBusConnection is not shared between the two
* paths .
*/
static gboolean
initable_init ( GInitable * initable ,
GCancellable * cancellable ,
GError * * error )
{
GDBusProxy * proxy = G_DBUS_PROXY ( initable ) ;
InitableAsyncInitableData * data ;
gboolean ret ;
ret = FALSE ;
if ( proxy - > priv - > bus_type ! = G_BUS_TYPE_NONE )
{
g_assert ( proxy - > priv - > connection = = NULL ) ;
proxy - > priv - > connection = g_bus_get_sync ( proxy - > priv - > bus_type ,
cancellable ,
error ) ;
if ( proxy - > priv - > connection = = NULL )
goto out ;
}
async_initable_init_first ( G_ASYNC_INITABLE ( initable ) ) ;
data = g_new0 ( InitableAsyncInitableData , 1 ) ;
data - > context = g_main_context_new ( ) ;
data - > loop = g_main_loop_new ( data - > context , FALSE ) ;
g_main_context_push_thread_default ( data - > context ) ;
async_initable_init_second_async ( G_ASYNC_INITABLE ( initable ) ,
G_PRIORITY_DEFAULT ,
cancellable ,
async_initable_init_async_cb ,
data ) ;
g_main_loop_run ( data - > loop ) ;
ret = async_initable_init_second_finish ( G_ASYNC_INITABLE ( initable ) ,
data - > res ,
error ) ;
g_main_context_pop_thread_default ( data - > context ) ;
g_main_context_unref ( data - > context ) ;
g_main_loop_unref ( data - > loop ) ;
g_object_unref ( data - > res ) ;
g_free ( data ) ;
out :
return ret ;
}
static void
initable_iface_init ( GInitableIface * initable_iface )
{
initable_iface - > init = initable_init ;
}
/* ---------------------------------------------------------------------------------------------------- */
2010-05-06 20:13:59 +02:00
/**
* g_dbus_proxy_new :
* @ connection : A # GDBusConnection .
* @ flags : Flags used when constructing the proxy .
2011-03-30 19:52:31 +02:00
* @ info : ( allow - none ) : A # GDBusInterfaceInfo specifying the minimal interface that @ proxy conforms to or % NULL .
* @ name : ( allow - none ) : A bus name ( well - known or unique ) or % NULL if @ connection is not a message bus connection .
2010-05-06 20:13:59 +02:00
* @ object_path : An object path .
* @ interface_name : A D - Bus interface name .
* @ cancellable : A # GCancellable or % NULL .
* @ callback : Callback function to invoke when the proxy is ready .
* @ user_data : User data to pass to @ callback .
*
2010-06-11 21:45:18 +02:00
* Creates a proxy for accessing @ interface_name on the remote object
* at @ object_path owned by @ name at @ connection and asynchronously
* loads D - Bus properties unless the
2010-08-18 16:52:28 +02:00
* % G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used . Connect to
2010-06-11 21:45:18 +02:00
* the # GDBusProxy : : g - properties - changed signal to get notified about
* property changes .
2010-05-06 20:13:59 +02:00
*
2010-08-18 16:52:28 +02:00
* If the % G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set , also sets up
2010-05-06 20:13:59 +02:00
* match rules for signals . Connect to the # GDBusProxy : : g - signal signal
* to handle signals from the remote object .
*
2010-06-11 21:45:18 +02:00
* If @ name is a well - known name and the
2010-08-18 16:52:28 +02:00
* % G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag isn ' t set and no name
2010-06-11 21:45:18 +02:00
* owner currently exists , the message bus will be requested to launch
* a name owner for the name .
*
2010-05-06 20:13:59 +02:00
* This is a failable asynchronous constructor - when the proxy is
* ready , @ callback will be invoked and you can use
* g_dbus_proxy_new_finish ( ) to get the result .
*
* See g_dbus_proxy_new_sync ( ) and for a synchronous version of this constructor .
2010-05-06 22:02:08 +02:00
*
2010-06-11 21:45:18 +02:00
* See < xref linkend = " gdbus-wellknown-proxy " / > for an example of how # GDBusProxy can be used .
*
2010-05-06 22:02:08 +02:00
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
void
g_dbus_proxy_new ( GDBusConnection * connection ,
GDBusProxyFlags flags ,
GDBusInterfaceInfo * info ,
2010-06-11 21:45:18 +02:00
const gchar * name ,
2010-05-06 20:13:59 +02:00
const gchar * object_path ,
const gchar * interface_name ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data )
{
g_return_if_fail ( G_IS_DBUS_CONNECTION ( connection ) ) ;
2010-06-11 21:45:18 +02:00
g_return_if_fail ( ( name = = NULL & & g_dbus_connection_get_unique_name ( connection ) = = NULL ) | | g_dbus_is_name ( name ) ) ;
2010-05-06 20:13:59 +02:00
g_return_if_fail ( g_variant_is_object_path ( object_path ) ) ;
g_return_if_fail ( g_dbus_is_interface_name ( interface_name ) ) ;
2010-06-11 21:45:18 +02:00
g_async_initable_new_async ( G_TYPE_DBUS_PROXY ,
2010-05-06 20:13:59 +02:00
G_PRIORITY_DEFAULT ,
cancellable ,
callback ,
user_data ,
" g-flags " , flags ,
" g-interface-info " , info ,
2010-06-11 21:45:18 +02:00
" g-name " , name ,
2010-05-06 20:13:59 +02:00
" g-connection " , connection ,
" g-object-path " , object_path ,
" g-interface-name " , interface_name ,
NULL ) ;
}
/**
* g_dbus_proxy_new_finish :
* @ res : A # GAsyncResult obtained from the # GAsyncReadyCallback function passed to g_dbus_proxy_new ( ) .
* @ error : Return location for error or % NULL .
*
* Finishes creating a # GDBusProxy .
*
* Returns : A # GDBusProxy or % NULL if @ error is set . Free with g_object_unref ( ) .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
GDBusProxy *
g_dbus_proxy_new_finish ( GAsyncResult * res ,
GError * * error )
{
GObject * object ;
GObject * source_object ;
source_object = g_async_result_get_source_object ( res ) ;
g_assert ( source_object ! = NULL ) ;
object = g_async_initable_new_finish ( G_ASYNC_INITABLE ( source_object ) ,
res ,
error ) ;
g_object_unref ( source_object ) ;
if ( object ! = NULL )
return G_DBUS_PROXY ( object ) ;
else
return NULL ;
}
/**
* g_dbus_proxy_new_sync :
* @ connection : A # GDBusConnection .
* @ flags : Flags used when constructing the proxy .
2010-07-15 15:32:45 +02:00
* @ info : ( allow - none ) : A # GDBusInterfaceInfo specifying the minimal interface that @ proxy conforms to or % NULL .
* @ name : ( allow - none ) : A bus name ( well - known or unique ) or % NULL if @ connection is not a message bus connection .
2010-05-06 20:13:59 +02:00
* @ object_path : An object path .
* @ interface_name : A D - Bus interface name .
2010-07-15 15:32:45 +02:00
* @ cancellable : ( allow - none ) : A # GCancellable or % NULL .
* @ error : ( allow - none ) : Return location for error or % NULL .
2010-05-06 20:13:59 +02:00
*
2010-06-11 21:45:18 +02:00
* Creates a proxy for accessing @ interface_name on the remote object
* at @ object_path owned by @ name at @ connection and synchronously
* loads D - Bus properties unless the
2010-08-18 16:52:28 +02:00
* % G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES flag is used .
2010-05-06 20:13:59 +02:00
*
2010-08-18 16:52:28 +02:00
* If the % G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS flag is not set , also sets up
2010-05-06 20:13:59 +02:00
* match rules for signals . Connect to the # GDBusProxy : : g - signal signal
* to handle signals from the remote object .
*
2010-06-11 21:45:18 +02:00
* If @ name is a well - known name and the
2010-08-18 16:52:28 +02:00
* % G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag isn ' t set and no name
2010-06-11 21:45:18 +02:00
* owner currently exists , the message bus will be requested to launch
* a name owner for the name .
*
2010-05-06 20:13:59 +02:00
* This is a synchronous failable constructor . See g_dbus_proxy_new ( )
* and g_dbus_proxy_new_finish ( ) for the asynchronous version .
*
2010-06-11 21:45:18 +02:00
* See < xref linkend = " gdbus-wellknown-proxy " / > for an example of how # GDBusProxy can be used .
*
2010-05-06 20:13:59 +02:00
* Returns : A # GDBusProxy or % NULL if error is set . Free with g_object_unref ( ) .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
GDBusProxy *
g_dbus_proxy_new_sync ( GDBusConnection * connection ,
GDBusProxyFlags flags ,
GDBusInterfaceInfo * info ,
2010-06-11 21:45:18 +02:00
const gchar * name ,
2010-05-06 20:13:59 +02:00
const gchar * object_path ,
const gchar * interface_name ,
GCancellable * cancellable ,
GError * * error )
{
GInitable * initable ;
g_return_val_if_fail ( G_IS_DBUS_CONNECTION ( connection ) , NULL ) ;
2010-06-11 21:45:18 +02:00
g_return_val_if_fail ( ( name = = NULL & & g_dbus_connection_get_unique_name ( connection ) = = NULL ) | |
g_dbus_is_name ( name ) , NULL ) ;
2010-05-06 20:13:59 +02:00
g_return_val_if_fail ( g_variant_is_object_path ( object_path ) , NULL ) ;
g_return_val_if_fail ( g_dbus_is_interface_name ( interface_name ) , NULL ) ;
2010-06-11 21:45:18 +02:00
initable = g_initable_new ( G_TYPE_DBUS_PROXY ,
2010-05-06 20:13:59 +02:00
cancellable ,
error ,
" g-flags " , flags ,
" g-interface-info " , info ,
2010-06-11 21:45:18 +02:00
" g-name " , name ,
2010-05-06 20:13:59 +02:00
" g-connection " , connection ,
" g-object-path " , object_path ,
" g-interface-name " , interface_name ,
NULL ) ;
if ( initable ! = NULL )
return G_DBUS_PROXY ( initable ) ;
else
return NULL ;
}
/* ---------------------------------------------------------------------------------------------------- */
2010-06-11 21:45:18 +02:00
/**
* g_dbus_proxy_new_for_bus :
* @ bus_type : A # GBusType .
* @ flags : Flags used when constructing the proxy .
2011-03-30 19:52:31 +02:00
* @ info : ( allow - none ) : A # GDBusInterfaceInfo specifying the minimal interface that @ proxy conforms to or % NULL .
2010-06-11 21:45:18 +02:00
* @ name : A bus name ( well - known or unique ) .
* @ object_path : An object path .
* @ interface_name : A D - Bus interface name .
* @ cancellable : A # GCancellable or % NULL .
* @ callback : Callback function to invoke when the proxy is ready .
* @ user_data : User data to pass to @ callback .
*
* Like g_dbus_proxy_new ( ) but takes a # GBusType instead of a # GDBusConnection .
*
* See < xref linkend = " gdbus-wellknown-proxy " / > for an example of how # GDBusProxy can be used .
*
* Since : 2.26
*/
void
g_dbus_proxy_new_for_bus ( GBusType bus_type ,
GDBusProxyFlags flags ,
GDBusInterfaceInfo * info ,
const gchar * name ,
const gchar * object_path ,
const gchar * interface_name ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data )
{
g_return_if_fail ( g_dbus_is_name ( name ) ) ;
g_return_if_fail ( g_variant_is_object_path ( object_path ) ) ;
g_return_if_fail ( g_dbus_is_interface_name ( interface_name ) ) ;
g_async_initable_new_async ( G_TYPE_DBUS_PROXY ,
G_PRIORITY_DEFAULT ,
cancellable ,
callback ,
user_data ,
" g-flags " , flags ,
" g-interface-info " , info ,
" g-name " , name ,
" g-bus-type " , bus_type ,
" g-object-path " , object_path ,
" g-interface-name " , interface_name ,
NULL ) ;
}
/**
* g_dbus_proxy_new_for_bus_finish :
* @ res : A # GAsyncResult obtained from the # GAsyncReadyCallback function passed to g_dbus_proxy_new_for_bus ( ) .
* @ error : Return location for error or % NULL .
*
* Finishes creating a # GDBusProxy .
*
* Returns : A # GDBusProxy or % NULL if @ error is set . Free with g_object_unref ( ) .
*
* Since : 2.26
*/
GDBusProxy *
g_dbus_proxy_new_for_bus_finish ( GAsyncResult * res ,
GError * * error )
{
return g_dbus_proxy_new_finish ( res , error ) ;
}
/**
* g_dbus_proxy_new_for_bus_sync :
* @ bus_type : A # GBusType .
* @ flags : Flags used when constructing the proxy .
2011-03-30 19:52:31 +02:00
* @ info : ( allow - none ) : A # GDBusInterfaceInfo specifying the minimal interface
* that @ proxy conforms to or % NULL .
2010-06-11 21:45:18 +02:00
* @ name : A bus name ( well - known or unique ) .
* @ object_path : An object path .
* @ interface_name : A D - Bus interface name .
* @ cancellable : A # GCancellable or % NULL .
* @ error : Return location for error or % NULL .
*
* Like g_dbus_proxy_new_sync ( ) but takes a # GBusType instead of a # GDBusConnection .
*
* See < xref linkend = " gdbus-wellknown-proxy " / > for an example of how # GDBusProxy can be used .
*
* Returns : A # GDBusProxy or % NULL if error is set . Free with g_object_unref ( ) .
*
* Since : 2.26
*/
GDBusProxy *
g_dbus_proxy_new_for_bus_sync ( GBusType bus_type ,
GDBusProxyFlags flags ,
GDBusInterfaceInfo * info ,
const gchar * name ,
const gchar * object_path ,
const gchar * interface_name ,
GCancellable * cancellable ,
GError * * error )
{
GInitable * initable ;
g_return_val_if_fail ( g_dbus_is_name ( name ) , NULL ) ;
g_return_val_if_fail ( g_variant_is_object_path ( object_path ) , NULL ) ;
g_return_val_if_fail ( g_dbus_is_interface_name ( interface_name ) , NULL ) ;
initable = g_initable_new ( G_TYPE_DBUS_PROXY ,
cancellable ,
error ,
" g-flags " , flags ,
" g-interface-info " , info ,
" g-name " , name ,
" g-bus-type " , bus_type ,
" g-object-path " , object_path ,
" g-interface-name " , interface_name ,
NULL ) ;
if ( initable ! = NULL )
return G_DBUS_PROXY ( initable ) ;
else
return NULL ;
}
/* ---------------------------------------------------------------------------------------------------- */
2010-05-06 20:13:59 +02:00
/**
* g_dbus_proxy_get_connection :
* @ proxy : A # GDBusProxy .
*
* Gets the connection @ proxy is for .
*
2010-09-24 23:24:41 +02:00
* Returns : ( transfer none ) : A # GDBusConnection owned by @ proxy . Do not free .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
GDBusConnection *
g_dbus_proxy_get_connection ( GDBusProxy * proxy )
{
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
return proxy - > priv - > connection ;
}
/**
* g_dbus_proxy_get_flags :
* @ proxy : A # GDBusProxy .
*
* Gets the flags that @ proxy was constructed with .
*
* Returns : Flags from the # GDBusProxyFlags enumeration .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
GDBusProxyFlags
g_dbus_proxy_get_flags ( GDBusProxy * proxy )
{
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , 0 ) ;
return proxy - > priv - > flags ;
}
/**
2010-06-11 21:45:18 +02:00
* g_dbus_proxy_get_name :
2010-05-06 20:13:59 +02:00
* @ proxy : A # GDBusProxy .
*
2010-06-11 21:45:18 +02:00
* Gets the name that @ proxy was constructed for .
2010-05-06 20:13:59 +02:00
*
* Returns : A string owned by @ proxy . Do not free .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
const gchar *
2010-06-11 21:45:18 +02:00
g_dbus_proxy_get_name ( GDBusProxy * proxy )
{
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
return proxy - > priv - > name ;
}
/**
* g_dbus_proxy_get_name_owner :
* @ proxy : A # GDBusProxy .
*
* The unique name that owns the name that @ proxy is for or % NULL if
* no - one currently owns that name . You may connect to the
* # GObject : : notify signal to track changes to the
* # GDBusProxy : g - name - owner property .
*
* Returns : The name owner or % NULL if no name owner exists . Free with g_free ( ) .
*
* Since : 2.26
*/
gchar *
g_dbus_proxy_get_name_owner ( GDBusProxy * proxy )
2010-05-06 20:13:59 +02:00
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
gchar * ret ;
2010-05-06 20:13:59 +02:00
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
ret = g_strdup ( proxy - > priv - > name_owner ) ;
G_UNLOCK ( properties_lock ) ;
return ret ;
2010-05-06 20:13:59 +02:00
}
/**
* g_dbus_proxy_get_object_path :
* @ proxy : A # GDBusProxy .
*
* Gets the object path @ proxy is for .
*
* Returns : A string owned by @ proxy . Do not free .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
const gchar *
g_dbus_proxy_get_object_path ( GDBusProxy * proxy )
{
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
return proxy - > priv - > object_path ;
}
/**
* g_dbus_proxy_get_interface_name :
* @ proxy : A # GDBusProxy .
*
* Gets the D - Bus interface name @ proxy is for .
*
* Returns : A string owned by @ proxy . Do not free .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
*/
2010-05-06 20:13:59 +02:00
const gchar *
g_dbus_proxy_get_interface_name ( GDBusProxy * proxy )
{
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
return proxy - > priv - > interface_name ;
}
/**
* g_dbus_proxy_get_default_timeout :
* @ proxy : A # GDBusProxy .
*
* Gets the timeout to use if - 1 ( specifying default timeout ) is
2010-05-10 17:47:08 +02:00
* passed as @ timeout_msec in the g_dbus_proxy_call ( ) and
* g_dbus_proxy_call_sync ( ) functions .
2010-05-06 20:13:59 +02:00
*
* See the # GDBusProxy : g - default - timeout property for more details .
*
* Returns : Timeout to use for @ proxy .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
gint
g_dbus_proxy_get_default_timeout ( GDBusProxy * proxy )
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
gint ret ;
2010-05-06 20:13:59 +02:00
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , - 1 ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
ret = proxy - > priv - > timeout_msec ;
G_UNLOCK ( properties_lock ) ;
return ret ;
2010-05-06 20:13:59 +02:00
}
/**
* g_dbus_proxy_set_default_timeout :
* @ proxy : A # GDBusProxy .
* @ timeout_msec : Timeout in milliseconds .
*
* Sets the timeout to use if - 1 ( specifying default timeout ) is
2010-05-10 17:47:08 +02:00
* passed as @ timeout_msec in the g_dbus_proxy_call ( ) and
* g_dbus_proxy_call_sync ( ) functions .
2010-05-06 20:13:59 +02:00
*
* See the # GDBusProxy : g - default - timeout property for more details .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
void
g_dbus_proxy_set_default_timeout ( GDBusProxy * proxy ,
gint timeout_msec )
{
g_return_if_fail ( G_IS_DBUS_PROXY ( proxy ) ) ;
g_return_if_fail ( timeout_msec = = - 1 | | timeout_msec > = 0 ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
if ( proxy - > priv - > timeout_msec ! = timeout_msec )
{
proxy - > priv - > timeout_msec = timeout_msec ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
g_object_notify ( G_OBJECT ( proxy ) , " g-default-timeout " ) ;
}
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
else
{
G_UNLOCK ( properties_lock ) ;
}
2010-05-06 20:13:59 +02:00
}
/**
* g_dbus_proxy_get_interface_info :
* @ proxy : A # GDBusProxy
*
2011-10-04 17:37:16 +02:00
* Returns the # GDBusInterfaceInfo , if any , specifying the interface
* that @ proxy conforms to . See the # GDBusProxy : g - interface - info
* property for more details .
2010-05-06 20:13:59 +02:00
*
* Returns : A # GDBusInterfaceInfo or % NULL . Do not unref the returned
* object , it is owned by @ proxy .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
GDBusInterfaceInfo *
g_dbus_proxy_get_interface_info ( GDBusProxy * proxy )
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
GDBusInterfaceInfo * ret ;
2010-05-06 20:13:59 +02:00
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
ret = proxy - > priv - > expected_interface ;
G_UNLOCK ( properties_lock ) ;
/* FIXME: returning a borrowed ref with no guarantee that nobody will
* call g_dbus_proxy_set_interface_info ( ) and make it invalid . . .
*/
return ret ;
2010-05-06 20:13:59 +02:00
}
/**
* g_dbus_proxy_set_interface_info :
* @ proxy : A # GDBusProxy
2011-03-30 19:52:31 +02:00
* @ info : ( allow - none ) : Minimum interface this proxy conforms to or % NULL to unset .
2010-05-06 20:13:59 +02:00
*
* Ensure that interactions with @ proxy conform to the given
2011-10-04 17:37:16 +02:00
* interface . See the # GDBusProxy : g - interface - info property for more
* details .
2010-05-06 22:02:08 +02:00
*
* Since : 2.26
2010-05-06 20:13:59 +02:00
*/
void
g_dbus_proxy_set_interface_info ( GDBusProxy * proxy ,
GDBusInterfaceInfo * info )
{
g_return_if_fail ( G_IS_DBUS_PROXY ( proxy ) ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
if ( proxy - > priv - > expected_interface ! = NULL )
2011-03-28 17:34:48 +02:00
{
g_dbus_interface_info_cache_release ( proxy - > priv - > expected_interface ) ;
g_dbus_interface_info_unref ( proxy - > priv - > expected_interface ) ;
}
2010-05-06 20:13:59 +02:00
proxy - > priv - > expected_interface = info ! = NULL ? g_dbus_interface_info_ref ( info ) : NULL ;
2011-03-28 17:34:48 +02:00
if ( proxy - > priv - > expected_interface ! = NULL )
g_dbus_interface_info_cache_build ( proxy - > priv - > expected_interface ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
}
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
2010-05-10 04:13:18 +02:00
maybe_split_method_name ( const gchar * method_name ,
gchar * * out_interface_name ,
const gchar * * out_method_name )
2010-05-06 20:13:59 +02:00
{
gboolean was_split ;
was_split = FALSE ;
g_assert ( out_interface_name ! = NULL ) ;
g_assert ( out_method_name ! = NULL ) ;
* out_interface_name = NULL ;
* out_method_name = NULL ;
if ( strchr ( method_name , ' . ' ) ! = NULL )
{
gchar * p ;
gchar * last_dot ;
p = g_strdup ( method_name ) ;
last_dot = strrchr ( p , ' . ' ) ;
* last_dot = ' \0 ' ;
* out_interface_name = p ;
* out_method_name = last_dot + 1 ;
was_split = TRUE ;
}
return was_split ;
}
2011-07-21 22:03:27 +02:00
typedef struct
{
GVariant * value ;
# ifdef G_OS_UNIX
GUnixFDList * fd_list ;
# endif
} ReplyData ;
static void
reply_data_free ( ReplyData * data )
{
g_variant_unref ( data - > value ) ;
# ifdef G_OS_UNIX
if ( data - > fd_list ! = NULL )
g_object_unref ( data - > fd_list ) ;
# endif
g_slice_free ( ReplyData , data ) ;
}
2010-05-06 20:13:59 +02:00
static void
reply_cb ( GDBusConnection * connection ,
GAsyncResult * res ,
gpointer user_data )
{
GSimpleAsyncResult * simple = G_SIMPLE_ASYNC_RESULT ( user_data ) ;
GVariant * value ;
GError * error ;
2011-07-21 22:03:27 +02:00
# ifdef G_OS_UNIX
GUnixFDList * fd_list ;
# endif
2010-05-06 20:13:59 +02:00
error = NULL ;
2011-07-21 22:03:27 +02:00
# ifdef G_OS_UNIX
value = g_dbus_connection_call_with_unix_fd_list_finish ( connection ,
& fd_list ,
res ,
& error ) ;
# else
2010-05-10 17:47:08 +02:00
value = g_dbus_connection_call_finish ( connection ,
res ,
& error ) ;
2011-07-21 22:03:27 +02:00
# endif
2010-05-06 20:13:59 +02:00
if ( error ! = NULL )
{
2010-09-23 13:02:50 +02:00
g_simple_async_result_take_error ( simple , error ) ;
2010-05-06 20:13:59 +02:00
}
else
{
2011-07-21 22:03:27 +02:00
ReplyData * data ;
data = g_slice_new0 ( ReplyData ) ;
data - > value = value ;
# ifdef G_OS_UNIX
data - > fd_list = fd_list ;
# endif
g_simple_async_result_set_op_res_gpointer ( simple , data , ( GDestroyNotify ) reply_data_free ) ;
2010-05-06 20:13:59 +02:00
}
/* no need to complete in idle since the method GDBusConnection already does */
g_simple_async_result_complete ( simple ) ;
2010-08-03 17:14:21 +02:00
g_object_unref ( simple ) ;
2010-05-06 20:13:59 +02:00
}
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* properties_lock must be held for as long as you will keep the
* returned value
*/
2010-05-06 20:13:59 +02:00
static const GDBusMethodInfo *
2011-10-04 17:37:16 +02:00
lookup_method_info ( GDBusProxy * proxy ,
const gchar * method_name )
2010-05-06 20:13:59 +02:00
{
2011-10-04 17:37:16 +02:00
const GDBusMethodInfo * info = NULL ;
2010-05-06 20:13:59 +02:00
2010-05-13 02:43:40 +02:00
if ( proxy - > priv - > expected_interface = = NULL )
2011-10-04 17:37:16 +02:00
goto out ;
2010-05-06 20:13:59 +02:00
info = g_dbus_interface_info_lookup_method ( proxy - > priv - > expected_interface , method_name ) ;
2011-10-04 17:37:16 +02:00
out :
2010-05-06 20:13:59 +02:00
return info ;
}
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
/* properties_lock must be held for as long as you will keep the
* returned value
*/
2010-08-18 17:35:25 +02:00
static const gchar *
get_destination_for_call ( GDBusProxy * proxy )
{
const gchar * ret ;
ret = NULL ;
/* If proxy->priv->name is a unique name, then proxy->priv->name_owner
* is never NULL and always the same as proxy - > priv - > name . We use this
* knowledge to avoid checking if proxy - > priv - > name is a unique or
* well - known name .
*/
ret = proxy - > priv - > name_owner ;
if ( ret ! = NULL )
goto out ;
if ( proxy - > priv - > flags & G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START )
goto out ;
ret = proxy - > priv - > name ;
out :
return ret ;
}
2011-07-21 22:03:27 +02:00
/* ---------------------------------------------------------------------------------------------------- */
static void
g_dbus_proxy_call_internal ( GDBusProxy * proxy ,
const gchar * method_name ,
GVariant * parameters ,
GDBusCallFlags flags ,
gint timeout_msec ,
GUnixFDList * fd_list ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data )
2010-05-06 20:13:59 +02:00
{
GSimpleAsyncResult * simple ;
gboolean was_split ;
gchar * split_interface_name ;
const gchar * split_method_name ;
const gchar * target_method_name ;
const gchar * target_interface_name ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
gchar * destination ;
2010-05-24 22:46:24 +02:00
GVariantType * reply_type ;
2010-05-06 20:13:59 +02:00
g_return_if_fail ( G_IS_DBUS_PROXY ( proxy ) ) ;
g_return_if_fail ( g_dbus_is_member_name ( method_name ) | | g_dbus_is_interface_name ( method_name ) ) ;
g_return_if_fail ( parameters = = NULL | | g_variant_is_of_type ( parameters , G_VARIANT_TYPE_TUPLE ) ) ;
g_return_if_fail ( timeout_msec = = - 1 | | timeout_msec > = 0 ) ;
2011-07-25 16:31:17 +02:00
# ifdef G_OS_UNIX
2011-07-21 22:03:27 +02:00
g_return_if_fail ( fd_list = = NULL | | G_IS_UNIX_FD_LIST ( fd_list ) ) ;
2011-07-25 16:31:17 +02:00
# else
g_return_if_fail ( fd_list = = NULL ) ;
# endif
2010-05-06 20:13:59 +02:00
2010-08-18 17:35:25 +02:00
reply_type = NULL ;
split_interface_name = NULL ;
2010-05-06 20:13:59 +02:00
simple = g_simple_async_result_new ( G_OBJECT ( proxy ) ,
callback ,
user_data ,
2011-07-21 22:03:27 +02:00
g_dbus_proxy_call_internal ) ;
2012-03-13 21:41:57 +01:00
g_simple_async_result_set_check_cancellable ( simple , cancellable ) ;
2010-05-06 20:13:59 +02:00
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
was_split = maybe_split_method_name ( method_name , & split_interface_name , & split_method_name ) ;
target_method_name = was_split ? split_method_name : method_name ;
target_interface_name = was_split ? split_interface_name : proxy - > priv - > interface_name ;
2010-06-22 23:48:35 +02:00
/* Warn if method is unexpected (cf. :g-interface-info) */
if ( ! was_split )
2010-08-18 17:35:25 +02:00
{
const GDBusMethodInfo * expected_method_info ;
2011-10-04 17:37:16 +02:00
expected_method_info = lookup_method_info ( proxy , target_method_name ) ;
2010-08-18 17:35:25 +02:00
if ( expected_method_info ! = NULL )
reply_type = _g_dbus_compute_complete_signature ( expected_method_info - > out_args ) ;
}
2010-05-06 20:13:59 +02:00
2010-08-18 17:35:25 +02:00
destination = NULL ;
if ( proxy - > priv - > name ! = NULL )
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
destination = g_strdup ( get_destination_for_call ( proxy ) ) ;
2010-08-18 17:35:25 +02:00
if ( destination = = NULL )
{
g_simple_async_result_set_error ( simple ,
G_IO_ERROR ,
G_IO_ERROR_FAILED ,
_ ( " Cannot invoke method; proxy is for a well-known name without an owner and proxy was constructed with the G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag " ) ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-08-18 17:35:25 +02:00
goto out ;
}
}
2010-05-24 22:46:24 +02:00
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2011-07-21 22:03:27 +02:00
# ifdef G_OS_UNIX
g_dbus_connection_call_with_unix_fd_list ( proxy - > priv - > connection ,
destination ,
proxy - > priv - > object_path ,
target_interface_name ,
target_method_name ,
parameters ,
reply_type ,
flags ,
timeout_msec = = - 1 ? proxy - > priv - > timeout_msec : timeout_msec ,
fd_list ,
cancellable ,
( GAsyncReadyCallback ) reply_cb ,
simple ) ;
# else
2010-05-10 17:47:08 +02:00
g_dbus_connection_call ( proxy - > priv - > connection ,
2010-08-18 17:35:25 +02:00
destination ,
2010-05-10 17:47:08 +02:00
proxy - > priv - > object_path ,
target_interface_name ,
target_method_name ,
parameters ,
2010-05-24 22:46:24 +02:00
reply_type ,
2010-05-10 17:47:08 +02:00
flags ,
timeout_msec = = - 1 ? proxy - > priv - > timeout_msec : timeout_msec ,
cancellable ,
( GAsyncReadyCallback ) reply_cb ,
simple ) ;
2011-07-21 22:03:27 +02:00
# endif
2010-05-06 20:13:59 +02:00
2010-08-18 17:35:25 +02:00
out :
2010-05-24 22:46:24 +02:00
if ( reply_type ! = NULL )
g_variant_type_free ( reply_type ) ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
g_free ( destination ) ;
2010-05-06 20:13:59 +02:00
g_free ( split_interface_name ) ;
}
2011-07-21 22:03:27 +02:00
static GVariant *
g_dbus_proxy_call_finish_internal ( GDBusProxy * proxy ,
GUnixFDList * * out_fd_list ,
GAsyncResult * res ,
GError * * error )
2010-05-06 20:13:59 +02:00
{
GSimpleAsyncResult * simple = G_SIMPLE_ASYNC_RESULT ( res ) ;
GVariant * value ;
2011-07-21 22:03:27 +02:00
ReplyData * data ;
2010-05-06 20:13:59 +02:00
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
g_return_val_if_fail ( G_IS_ASYNC_RESULT ( res ) , NULL ) ;
g_return_val_if_fail ( error = = NULL | | * error = = NULL , NULL ) ;
2011-07-21 22:03:27 +02:00
g_warn_if_fail ( g_simple_async_result_get_source_tag ( simple ) = = g_dbus_proxy_call_internal ) ;
2010-05-06 20:13:59 +02:00
value = NULL ;
if ( g_simple_async_result_propagate_error ( simple , error ) )
goto out ;
2011-07-21 22:03:27 +02:00
data = g_simple_async_result_get_op_res_gpointer ( simple ) ;
value = g_variant_ref ( data - > value ) ;
# ifdef G_OS_UNIX
if ( out_fd_list ! = NULL )
* out_fd_list = data - > fd_list ! = NULL ? g_object_ref ( data - > fd_list ) : NULL ;
# endif
2010-05-06 20:13:59 +02:00
out :
return value ;
}
2011-07-21 22:03:27 +02:00
static GVariant *
g_dbus_proxy_call_sync_internal ( GDBusProxy * proxy ,
const gchar * method_name ,
GVariant * parameters ,
GDBusCallFlags flags ,
gint timeout_msec ,
GUnixFDList * fd_list ,
GUnixFDList * * out_fd_list ,
GCancellable * cancellable ,
GError * * error )
2010-05-06 20:13:59 +02:00
{
GVariant * ret ;
gboolean was_split ;
gchar * split_interface_name ;
const gchar * split_method_name ;
2010-05-10 04:13:18 +02:00
const gchar * target_method_name ;
const gchar * target_interface_name ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
gchar * destination ;
2010-05-24 22:46:24 +02:00
GVariantType * reply_type ;
2010-05-06 20:13:59 +02:00
g_return_val_if_fail ( G_IS_DBUS_PROXY ( proxy ) , NULL ) ;
g_return_val_if_fail ( g_dbus_is_member_name ( method_name ) | | g_dbus_is_interface_name ( method_name ) , NULL ) ;
g_return_val_if_fail ( parameters = = NULL | | g_variant_is_of_type ( parameters , G_VARIANT_TYPE_TUPLE ) , NULL ) ;
g_return_val_if_fail ( timeout_msec = = - 1 | | timeout_msec > = 0 , NULL ) ;
2011-07-25 16:31:17 +02:00
# ifdef G_OS_UNIX
2011-07-21 22:03:27 +02:00
g_return_val_if_fail ( fd_list = = NULL | | G_IS_UNIX_FD_LIST ( fd_list ) , NULL ) ;
2011-07-25 16:31:17 +02:00
# else
g_return_val_if_fail ( fd_list = = NULL , NULL ) ;
# endif
2010-05-06 20:13:59 +02:00
g_return_val_if_fail ( error = = NULL | | * error = = NULL , NULL ) ;
2010-08-18 17:35:25 +02:00
reply_type = NULL ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_LOCK ( properties_lock ) ;
2010-05-06 20:13:59 +02:00
was_split = maybe_split_method_name ( method_name , & split_interface_name , & split_method_name ) ;
target_method_name = was_split ? split_method_name : method_name ;
target_interface_name = was_split ? split_interface_name : proxy - > priv - > interface_name ;
2010-08-18 17:35:25 +02:00
/* Warn if method is unexpected (cf. :g-interface-info) */
if ( ! was_split )
2010-05-06 20:13:59 +02:00
{
2010-08-18 17:35:25 +02:00
const GDBusMethodInfo * expected_method_info ;
2011-10-04 17:37:16 +02:00
expected_method_info = lookup_method_info ( proxy , target_method_name ) ;
2010-08-18 17:35:25 +02:00
if ( expected_method_info ! = NULL )
reply_type = _g_dbus_compute_complete_signature ( expected_method_info - > out_args ) ;
2010-05-06 20:13:59 +02:00
}
2010-08-18 17:35:25 +02:00
destination = NULL ;
if ( proxy - > priv - > name ! = NULL )
2010-05-06 20:13:59 +02:00
{
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
destination = g_strdup ( get_destination_for_call ( proxy ) ) ;
2010-08-18 17:35:25 +02:00
if ( destination = = NULL )
{
g_set_error_literal ( error ,
G_IO_ERROR ,
G_IO_ERROR_FAILED ,
_ ( " Cannot invoke method; proxy is for a well-known name without an owner and proxy was constructed with the G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag " ) ) ;
2010-09-04 19:24:50 +02:00
ret = NULL ;
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2010-08-18 17:35:25 +02:00
goto out ;
}
2010-05-06 20:13:59 +02:00
}
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
G_UNLOCK ( properties_lock ) ;
2011-07-21 22:03:27 +02:00
# ifdef G_OS_UNIX
ret = g_dbus_connection_call_with_unix_fd_list_sync ( proxy - > priv - > connection ,
destination ,
proxy - > priv - > object_path ,
target_interface_name ,
target_method_name ,
parameters ,
reply_type ,
flags ,
timeout_msec = = - 1 ? proxy - > priv - > timeout_msec : timeout_msec ,
fd_list ,
out_fd_list ,
cancellable ,
error ) ;
# else
2010-05-10 17:47:08 +02:00
ret = g_dbus_connection_call_sync ( proxy - > priv - > connection ,
2010-08-18 17:35:25 +02:00
destination ,
2010-05-10 17:47:08 +02:00
proxy - > priv - > object_path ,
target_interface_name ,
target_method_name ,
parameters ,
2010-05-24 22:46:24 +02:00
reply_type ,
2010-05-10 17:47:08 +02:00
flags ,
timeout_msec = = - 1 ? proxy - > priv - > timeout_msec : timeout_msec ,
cancellable ,
error ) ;
2011-07-21 22:03:27 +02:00
# endif
2010-05-24 22:46:24 +02:00
2010-08-18 17:35:25 +02:00
out :
2010-05-24 22:46:24 +02:00
if ( reply_type ! = NULL )
g_variant_type_free ( reply_type ) ;
2010-05-06 20:13:59 +02:00
GDBusProxy: hold properties_lock while using any mutable property
This changes the meaning of "properties_lock" from "lock for D-Bus
properties" to "lock for GObject properties".
The most common problem, and the only one I've reproduced in a regression
test, is name_owner, which can be updated by the thread that owns
the GDBusProxy's main context (i.e. the thread-default main context of
the thread that constructed it) at the same time that a blocking call
is made. When a GDBusProxy is constructed in a thread-pool thread for
short-term use, the main context will typically be the global default
main context (which is actively running in the main thread!), making
this extremely problematic.
The interface info is perhaps a theoretical concern - one thread could
conceivably set it at the same time that another thread uses it, but only
in relatively pathological situations. The current API for this does have
the problem that it returns a borrowed ref, but interface info is
hopefully permanent anyway.
The default timeout is probably only a theoretical concern - it's just an
int, so writes are indivisible, and there's no worry about whether
something has been freed - but to be safe, let's hold the lock for that
too.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=656039
Bug-NB: NB#259760
Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-08-15 16:59:45 +02:00
g_free ( destination ) ;
2010-05-06 20:13:59 +02:00
g_free ( split_interface_name ) ;
return ret ;
}
/* ---------------------------------------------------------------------------------------------------- */
2011-04-08 21:14:47 +02:00
2011-07-21 22:03:27 +02:00
/**
* g_dbus_proxy_call :
* @ proxy : A # GDBusProxy .
* @ method_name : Name of method to invoke .
* @ parameters : ( allow - none ) : A # GVariant tuple with parameters for the signal or % NULL if not passing parameters .
* @ flags : Flags from the # GDBusCallFlags enumeration .
* @ timeout_msec : The timeout in milliseconds ( with % G_MAXINT meaning
* " infinite " ) or - 1 to use the proxy default timeout .
* @ cancellable : A # GCancellable or % NULL .
* @ callback : A # GAsyncReadyCallback to call when the request is satisfied or % NULL if you don ' t
* care about the result of the method invocation .
* @ user_data : The data to pass to @ callback .
*
* Asynchronously invokes the @ method_name method on @ proxy .
*
* If @ method_name contains any dots , then @ name is split into interface and
* method name parts . This allows using @ proxy for invoking methods on
* other interfaces .
*
* If the # GDBusConnection associated with @ proxy is closed then
* the operation will fail with % G_IO_ERROR_CLOSED . If
* @ cancellable is canceled , the operation will fail with
* % G_IO_ERROR_CANCELLED . If @ parameters contains a value not
* compatible with the D - Bus protocol , the operation fails with
* % G_IO_ERROR_INVALID_ARGUMENT .
*
* If the @ parameters # GVariant is floating , it is consumed . This allows
* convenient ' inline ' use of g_variant_new ( ) , e . g . :
* | [
* g_dbus_proxy_call ( proxy ,
* " TwoStrings " ,
* g_variant_new ( " (ss) " ,
* " Thing One " ,
* " Thing Two " ) ,
* G_DBUS_CALL_FLAGS_NONE ,
* - 1 ,
* NULL ,
* ( GAsyncReadyCallback ) two_strings_done ,
* & amp ; data ) ;
* ] |
*
2011-10-04 17:37:16 +02:00
* If @ proxy has an expected interface ( see
* # GDBusProxy : g - interface - info ) and @ method_name is referenced by it ,
* then the return value is checked against the return type .
*
2011-07-21 22:03:27 +02:00
* This is an asynchronous method . When the operation is finished ,
* @ callback will be invoked in the
* < link linkend = " g-main-context-push-thread-default " > thread - default main loop < / link >
* of the thread you are calling this method from .
* You can then call g_dbus_proxy_call_finish ( ) to get the result of
* the operation . See g_dbus_proxy_call_sync ( ) for the synchronous
* version of this method .
*
* Since : 2.26
*/
void
g_dbus_proxy_call ( GDBusProxy * proxy ,
const gchar * method_name ,
GVariant * parameters ,
GDBusCallFlags flags ,
gint timeout_msec ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data )
{
2011-08-17 10:01:14 +02:00
g_dbus_proxy_call_internal ( proxy , method_name , parameters , flags , timeout_msec , NULL , cancellable , callback , user_data ) ;
2011-07-21 22:03:27 +02:00
}
/**
* g_dbus_proxy_call_finish :
* @ proxy : A # GDBusProxy .
* @ res : A # GAsyncResult obtained from the # GAsyncReadyCallback passed to g_dbus_proxy_call ( ) .
* @ error : Return location for error or % NULL .
*
* Finishes an operation started with g_dbus_proxy_call ( ) .
*
* Returns : % NULL if @ error is set . Otherwise a # GVariant tuple with
* return values . Free with g_variant_unref ( ) .
*
* Since : 2.26
*/
GVariant *
g_dbus_proxy_call_finish ( GDBusProxy * proxy ,
GAsyncResult * res ,
GError * * error )
{
return g_dbus_proxy_call_finish_internal ( proxy , NULL , res , error ) ;
}
/**
* g_dbus_proxy_call_sync :
* @ proxy : A # GDBusProxy .
* @ method_name : Name of method to invoke .
* @ parameters : ( allow - none ) : A # GVariant tuple with parameters for the signal
* or % NULL if not passing parameters .
* @ flags : Flags from the # GDBusCallFlags enumeration .
* @ timeout_msec : The timeout in milliseconds ( with % G_MAXINT meaning
* " infinite " ) or - 1 to use the proxy default timeout .
* @ cancellable : A # GCancellable or % NULL .
* @ error : Return location for error or % NULL .
*
* Synchronously invokes the @ method_name method on @ proxy .
*
* If @ method_name contains any dots , then @ name is split into interface and
* method name parts . This allows using @ proxy for invoking methods on
* other interfaces .
*
* If the # GDBusConnection associated with @ proxy is disconnected then
* the operation will fail with % G_IO_ERROR_CLOSED . If
* @ cancellable is canceled , the operation will fail with
* % G_IO_ERROR_CANCELLED . If @ parameters contains a value not
* compatible with the D - Bus protocol , the operation fails with
* % G_IO_ERROR_INVALID_ARGUMENT .
*
* If the @ parameters # GVariant is floating , it is consumed . This allows
* convenient ' inline ' use of g_variant_new ( ) , e . g . :
* | [
* g_dbus_proxy_call_sync ( proxy ,
* " TwoStrings " ,
* g_variant_new ( " (ss) " ,
* " Thing One " ,
* " Thing Two " ) ,
* G_DBUS_CALL_FLAGS_NONE ,
* - 1 ,
* NULL ,
* & amp ; error ) ;
* ] |
*
* The calling thread is blocked until a reply is received . See
* g_dbus_proxy_call ( ) for the asynchronous version of this
* method .
*
2011-10-04 17:37:16 +02:00
* If @ proxy has an expected interface ( see
* # GDBusProxy : g - interface - info ) and @ method_name is referenced by it ,
* then the return value is checked against the return type .
*
2011-07-21 22:03:27 +02:00
* Returns : % NULL if @ error is set . Otherwise a # GVariant tuple with
* return values . Free with g_variant_unref ( ) .
*
* Since : 2.26
*/
GVariant *
g_dbus_proxy_call_sync ( GDBusProxy * proxy ,
const gchar * method_name ,
GVariant * parameters ,
GDBusCallFlags flags ,
gint timeout_msec ,
GCancellable * cancellable ,
GError * * error )
{
return g_dbus_proxy_call_sync_internal ( proxy , method_name , parameters , flags , timeout_msec , NULL , NULL , cancellable , error ) ;
}
/* ---------------------------------------------------------------------------------------------------- */
# ifdef G_OS_UNIX
/**
* g_dbus_proxy_call_with_unix_fd_list :
* @ proxy : A # GDBusProxy .
* @ method_name : Name of method to invoke .
* @ parameters : ( allow - none ) : A # GVariant tuple with parameters for the signal or % NULL if not passing parameters .
* @ flags : Flags from the # GDBusCallFlags enumeration .
* @ timeout_msec : The timeout in milliseconds ( with % G_MAXINT meaning
* " infinite " ) or - 1 to use the proxy default timeout .
* @ fd_list : ( allow - none ) : A # GUnixFDList or % NULL .
* @ cancellable : A # GCancellable or % NULL .
* @ callback : A # GAsyncReadyCallback to call when the request is satisfied or % NULL if you don ' t
* care about the result of the method invocation .
* @ user_data : The data to pass to @ callback .
*
* Like g_dbus_proxy_call ( ) but also takes a # GUnixFDList object .
*
* This method is only available on UNIX .
*
* Since : 2.30
*/
void
g_dbus_proxy_call_with_unix_fd_list ( GDBusProxy * proxy ,
const gchar * method_name ,
GVariant * parameters ,
GDBusCallFlags flags ,
gint timeout_msec ,
GUnixFDList * fd_list ,
GCancellable * cancellable ,
GAsyncReadyCallback callback ,
gpointer user_data )
{
2011-08-17 10:01:14 +02:00
g_dbus_proxy_call_internal ( proxy , method_name , parameters , flags , timeout_msec , fd_list , cancellable , callback , user_data ) ;
2011-07-21 22:03:27 +02:00
}
/**
* g_dbus_proxy_call_with_unix_fd_list_finish :
* @ proxy : A # GDBusProxy .
* @ out_fd_list : ( out ) : Return location for a # GUnixFDList or % NULL .
* @ res : A # GAsyncResult obtained from the # GAsyncReadyCallback passed to g_dbus_proxy_call_with_unix_fd_list ( ) .
* @ error : Return location for error or % NULL .
*
* Finishes an operation started with g_dbus_proxy_call_with_unix_fd_list ( ) .
*
* Returns : % NULL if @ error is set . Otherwise a # GVariant tuple with
* return values . Free with g_variant_unref ( ) .
*
* Since : 2.30
*/
GVariant *
g_dbus_proxy_call_with_unix_fd_list_finish ( GDBusProxy * proxy ,
GUnixFDList * * out_fd_list ,
GAsyncResult * res ,
GError * * error )
{
return g_dbus_proxy_call_finish_internal ( proxy , out_fd_list , res , error ) ;
}
/**
* g_dbus_proxy_call_with_unix_fd_list_sync :
* @ proxy : A # GDBusProxy .
* @ method_name : Name of method to invoke .
* @ parameters : ( allow - none ) : A # GVariant tuple with parameters for the signal
* or % NULL if not passing parameters .
* @ flags : Flags from the # GDBusCallFlags enumeration .
* @ timeout_msec : The timeout in milliseconds ( with % G_MAXINT meaning
* " infinite " ) or - 1 to use the proxy default timeout .
* @ fd_list : ( allow - none ) : A # GUnixFDList or % NULL .
* @ out_fd_list : ( out ) : Return location for a # GUnixFDList or % NULL .
* @ cancellable : A # GCancellable or % NULL .
* @ error : Return location for error or % NULL .
*
* Like g_dbus_proxy_call_sync ( ) but also takes and returns # GUnixFDList objects .
*
* This method is only available on UNIX .
*
* Returns : % NULL if @ error is set . Otherwise a # GVariant tuple with
* return values . Free with g_variant_unref ( ) .
*
* Since : 2.30
*/
GVariant *
g_dbus_proxy_call_with_unix_fd_list_sync ( GDBusProxy * proxy ,
const gchar * method_name ,
GVariant * parameters ,
GDBusCallFlags flags ,
gint timeout_msec ,
GUnixFDList * fd_list ,
GUnixFDList * * out_fd_list ,
GCancellable * cancellable ,
GError * * error )
{
return g_dbus_proxy_call_sync_internal ( proxy , method_name , parameters , flags , timeout_msec , fd_list , out_fd_list , cancellable , error ) ;
}
# endif /* G_OS_UNIX */
/* ---------------------------------------------------------------------------------------------------- */
2011-04-08 21:14:47 +02:00
static GDBusInterfaceInfo *
_g_dbus_proxy_get_info ( GDBusInterface * interface )
{
GDBusProxy * proxy = G_DBUS_PROXY ( interface ) ;
return g_dbus_proxy_get_interface_info ( proxy ) ;
}
static GDBusObject *
_g_dbus_proxy_get_object ( GDBusInterface * interface )
{
2011-04-08 22:12:33 +02:00
GDBusProxy * proxy = G_DBUS_PROXY ( interface ) ;
return proxy - > priv - > object ;
2011-04-08 21:14:47 +02:00
}
2012-01-26 20:16:28 +01:00
static GDBusObject *
_g_dbus_proxy_dup_object ( GDBusInterface * interface )
{
GDBusProxy * proxy = G_DBUS_PROXY ( interface ) ;
GDBusObject * ret = NULL ;
G_LOCK ( properties_lock ) ;
if ( proxy - > priv - > object ! = NULL )
ret = g_object_ref ( proxy - > priv - > object ) ;
G_UNLOCK ( properties_lock ) ;
return ret ;
}
2011-04-08 21:14:47 +02:00
static void
_g_dbus_proxy_set_object ( GDBusInterface * interface ,
GDBusObject * object )
{
2011-04-08 22:12:33 +02:00
GDBusProxy * proxy = G_DBUS_PROXY ( interface ) ;
2012-01-26 20:16:28 +01:00
G_LOCK ( properties_lock ) ;
2011-04-08 22:12:33 +02:00
if ( proxy - > priv - > object ! = NULL )
g_object_remove_weak_pointer ( G_OBJECT ( proxy - > priv - > object ) , ( gpointer * ) & proxy - > priv - > object ) ;
proxy - > priv - > object = object ;
if ( proxy - > priv - > object ! = NULL )
g_object_add_weak_pointer ( G_OBJECT ( proxy - > priv - > object ) , ( gpointer * ) & proxy - > priv - > object ) ;
2012-01-26 20:16:28 +01:00
G_UNLOCK ( properties_lock ) ;
2011-04-08 21:14:47 +02:00
}
static void
dbus_interface_iface_init ( GDBusInterfaceIface * dbus_interface_iface )
{
dbus_interface_iface - > get_info = _g_dbus_proxy_get_info ;
dbus_interface_iface - > get_object = _g_dbus_proxy_get_object ;
2012-01-26 20:16:28 +01:00
dbus_interface_iface - > dup_object = _g_dbus_proxy_dup_object ;
2011-04-08 21:14:47 +02:00
dbus_interface_iface - > set_object = _g_dbus_proxy_set_object ;
}
/* ---------------------------------------------------------------------------------------------------- */