pkgsrc/sysutils/upower/patches/patch-libupower-glib_up-client.c
bsiegert d857076534 Fix segfaults when upower is not running.
On my system, these patches stop xfsettingsd (from XFCE) from crashing
and dumping core during session startup. Thus, it can actually apply the
settings it is supposed to.

I just wish upstream had done a bugfix release, the patches are from 2016 :(

Fixes PR pkg/53455, which I filed :)
ok youri@
2018-07-18 19:18:07 +00:00

169 lines
5.2 KiB
C

$NetBSD: patch-libupower-glib_up-client.c,v 1.1 2018/07/18 19:18:07 bsiegert Exp $
From 932a6a39e35754be571e1274aec4730fd42dba13 Mon Sep 17 00:00:00 2001
From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Wed, 18 May 2016 09:22:43 +0200
Subject: [PATCH 1/9] lib: Add proper error and cancellable handling to
UpClient constructor
A GObject's _init() should never fail or block, but this is currently the case
as up_client_init() connects to upowerd on D-Bus. Convert this to the GInitable
interface and provide a new constructor up_client_new_full() which accepts a
GCancellable and GError, so that clients can do proper error handling
and reporting.
This changes up_client_new() to return NULL when connecting to upowerd fails.
This provides a more well-defined behaviour in this case as clients can check
for this and our methods stop segfaulting as they have checks like
g_return_val_if_fail (UP_IS_CLIENT (client), ...)
Previously we returned a valid object, but trying to call any method on it
segfaulted due to the NULL D-Bus proxy, so client code had no chance to check
whether the UpClient object was really valid.
https://bugs.freedesktop.org/show_bug.cgi?id=95350
--- libupower-glib/up-client.c
+++ libupower-glib/up-client.c
@@ -39,9 +39,10 @@
#include "up-daemon-generated.h"
#include "up-device.h"
-static void up_client_class_init (UpClientClass *klass);
-static void up_client_init (UpClient *client);
-static void up_client_finalize (GObject *object);
+static void up_client_class_init (UpClientClass *klass);
+static void up_client_initable_iface_init (GInitableIface *iface);
+static void up_client_init (UpClient *client);
+static void up_client_finalize (GObject *object);
#define UP_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_CLIENT, UpClientPrivate))
@@ -73,7 +74,8 @@ enum {
static guint signals [UP_CLIENT_LAST_SIGNAL] = { 0 };
static gpointer up_client_object = NULL;
-G_DEFINE_TYPE (UpClient, up_client, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_CODE (UpClient, up_client, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, up_client_initable_iface_init))
/**
* up_client_get_devices:
@@ -434,11 +436,10 @@ up_client_class_init (UpClientClass *klass)
* up_client_init:
* @client: This class instance
*/
-static void
-up_client_init (UpClient *client)
+static gboolean
+up_client_initable_init (GInitable *initable, GCancellable *cancellable, GError **error)
{
- GError *error = NULL;
-
+ UpClient *client = UP_CLIENT (initable);
client->priv = UP_CLIENT_GET_PRIVATE (client);
/* connect to main interface */
@@ -446,13 +447,10 @@ up_client_init (UpClient *client)
G_DBUS_PROXY_FLAGS_NONE,
"org.freedesktop.UPower",
"/org/freedesktop/UPower",
- NULL,
- &error);
- if (client->priv->proxy == NULL) {
- g_warning ("Couldn't connect to proxy: %s", error->message);
- g_error_free (error);
- return;
- }
+ cancellable,
+ error);
+ if (client->priv->proxy == NULL)
+ return FALSE;
/* all callbacks */
g_signal_connect (client->priv->proxy, "device-added",
@@ -461,6 +459,23 @@ up_client_init (UpClient *client)
G_CALLBACK (up_device_removed_cb), client);
g_signal_connect (client->priv->proxy, "notify",
G_CALLBACK (up_client_notify_cb), client);
+
+ return TRUE;
+}
+
+static void
+up_client_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = up_client_initable_init;
+}
+
+/*
+ * up_client_init:
+ * @client: This class instance
+ */
+static void
+up_client_init (UpClient *client)
+{
}
/*
@@ -482,23 +497,52 @@ up_client_finalize (GObject *object)
}
/**
- * up_client_new:
+ * up_client_new_full:
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
*
- * Creates a new #UpClient object.
+ * Creates a new #UpClient object. If connecting to upowerd on D-Bus fails,
+ % this returns %NULL and sets @error.
*
- * Return value: a new UpClient object.
+ * Return value: a new UpClient object, or %NULL on failure.
*
- * Since: 0.9.0
+ * Since: 0.99.5
**/
UpClient *
-up_client_new (void)
+up_client_new_full (GCancellable *cancellable, GError **error)
{
if (up_client_object != NULL) {
g_object_ref (up_client_object);
} else {
- up_client_object = g_object_new (UP_TYPE_CLIENT, NULL);
- g_object_add_weak_pointer (up_client_object, &up_client_object);
+ up_client_object = g_initable_new (UP_TYPE_CLIENT, cancellable, error, NULL);
+ if (up_client_object)
+ g_object_add_weak_pointer (up_client_object, &up_client_object);
}
return UP_CLIENT (up_client_object);
}
+/**
+ * up_client_new:
+ *
+ * Creates a new #UpClient object. If connecting to upowerd on D-Bus fails,
+ * this returns %NULL and prints out a warning with the error message.
+ * Consider using up_client_new_full() instead which allows you to handle errors
+ * and cancelling long operations yourself.
+ *
+ * Return value: a new UpClient object, or %NULL on failure.
+ *
+ * Since: 0.9.0
+ **/
+UpClient *
+up_client_new (void)
+{
+ GError *error = NULL;
+ UpClient *client;
+ client = up_client_new_full (NULL, &error);
+ if (client == NULL) {
+ g_warning ("Couldn't connect to proxy: %s", error->message);
+ g_error_free (error);
+ }
+ return client;
+}
+