[lxc-devel] [PATCH] cgmanager: avoid stray dbus connections

Stéphane Graber stgraber at ubuntu.com
Tue Mar 11 14:55:59 UTC 2014


On Mon, Mar 10, 2014 at 09:41:34PM -0500, Serge Hallyn wrote:
> There are two parts to this fix.
> 
> First, create a private DBusConnection manually, instead of using
> nih_dbus_connect.  The latter always creates a shared connection,
> which cannot be closed.  Note: creating an actual shared connection,
> mutexing it among all threads, and creating per-thread proxies would
> be an alternative - however we don't want long-lived connections as
> they tend not to be reliable (especially if cgmanager restarts).
> 
> Second, use pthread_setspecific to create per-thread keys which can
> be associated with destructors.  Specify a destructor which closes
> the dbus connection.  If a thread dies while holding cgmanager,
> the connection will be closed.  Otherwise, we close the connection
> and unset the key.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Acked-by: Stéphane Graber <stgraber at ubuntu.com>

> ---
>  src/lxc/cgmanager.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 47 insertions(+), 2 deletions(-)
> 
> diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c
> index c80a136..4cf6397 100644
> --- a/src/lxc/cgmanager.c
> +++ b/src/lxc/cgmanager.c
> @@ -70,10 +70,42 @@ struct cgm_data {
>  static __thread NihDBusProxy *cgroup_manager = NULL;
>  static __thread DBusConnection *connection = NULL;
>  static __thread bool cgm_keep_connection = false;
> +
> +
> +struct cgm_key_t {
> +	DBusConnection *connection;
> +	NihDBusProxy *cgmanager;
> +} cgm_key;
> +
> +void destructor(void *arg) {
> +	struct cgm_key_t *cgm_key = arg;
> +	nih_free(cgm_key->cgmanager);
> +	dbus_connection_flush(cgm_key->connection);
> +	dbus_connection_close(cgm_key->connection);
> +	dbus_connection_unref(cgm_key->connection);
> +}
> +static pthread_key_t key;
> +static void make_key() {
> +	pthread_key_create(&key, destructor);
> +}
> +
> +static void init_cgm_destructor(DBusConnection *c, NihDBusProxy *cgm)
> +{
> +	static pthread_once_t key_once = PTHREAD_ONCE_INIT;
> +	pthread_once(&key_once, make_key);
> +	cgm_key.connection = c;
> +	cgm_key.cgmanager = cgm;
> +	if (!cgm)
> +		pthread_setspecific(key, NULL);
> +	else if (pthread_getspecific(key) == NULL)
> +		pthread_setspecific(key, &cgm_key);
> +}
> +
>  #else
>  static NihDBusProxy *cgroup_manager = NULL;
>  static DBusConnection *connection = NULL;
>  static bool cgm_keep_connection = false;
> +static inline void init_cgm_destructor(DBusConnection *c, NihDBusProxy *cgm) { }
>  #endif
>  
>  static struct cgroup_ops cgmanager_ops;
> @@ -87,9 +119,13 @@ static void cgm_dbus_disconnect(void)
>  	if (cgroup_manager)
>  		nih_free(cgroup_manager);
>  	cgroup_manager = NULL;
> -	if (connection)
> +	if (connection) {
> +		dbus_connection_flush(connection);
> +		dbus_connection_close(connection);
>  		dbus_connection_unref(connection);
> +	}
>  	connection = NULL;
> +	init_cgm_destructor(NULL, NULL);
>  }
>  
>  #define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock"
> @@ -105,14 +141,22 @@ static bool do_cgm_dbus_connect(void)
>  
>  	dbus_error_init(&dbus_error);
>  
> -	connection = nih_dbus_connect(CGMANAGER_DBUS_SOCK, NULL);
> +	connection = dbus_connection_open_private(CGMANAGER_DBUS_SOCK, &dbus_error);
>  	if (!connection) {
> +		ERROR("Failed opening dbus connection: %s: %s",
> +				dbus_error.name, dbus_error.message);
> +		dbus_error_free(&dbus_error);
> +		return false;
> +	}
> +	if (nih_dbus_setup(connection, NULL) < 0) {
>  		NihError *nerr;
>  		nerr = nih_error_get();
>  		DEBUG("Unable to open cgmanager connection at %s: %s", CGMANAGER_DBUS_SOCK,
>  			nerr->message);
>  		nih_free(nerr);
>  		dbus_error_free(&dbus_error);
> +		dbus_connection_unref(connection);
> +		connection = NULL;
>  		return false;
>  	}
>  	dbus_connection_set_exit_on_disconnect(connection, FALSE);
> @@ -138,6 +182,7 @@ static bool do_cgm_dbus_connect(void)
>  		cgm_dbus_disconnect();
>  		return false;
>  	}
> +	init_cgm_destructor(connection, cgroup_manager);
>  	return true;
>  }
>  
> -- 
> 1.9.0
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20140311/6bbc9995/attachment.pgp>


More information about the lxc-devel mailing list