summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2011-09-22 16:54:50 +0100
committerWill Thompson <will.thompson@collabora.co.uk>2011-09-23 11:28:31 +0100
commit2981787353f9862c076cf1c72484c4d5ea234999 (patch)
treea29d33b785f8a83d3aeb6cab5a344bd88b4ef004
parent4695c8fe269d04eff269522dc6a0f67795a07dac (diff)
Master: poison singleton pointer when disposed
Previously, when the 'default' instance of McdMaster (i.e., the singleton) was disposed, the 'default_master' variable was left pointing to it. This is basically fine in practice, since the McdMaster is meant to survive for the lifetime of the connection. But I hit a weird crash (caused by the test suite's version of MC waiting 5 seconds after the McdMaster is destroyed before closing, which interacts badly with the reconnection timeout being less than 5 seconds) and it would have been much clearer what was happening if 'default_master' had held a known-bad address rather than a possibly-valid pointer to a freed object. This doesn't change the behaviour of the code in any significant way: we'll still crash in this situation. But as far as I can tell the bug is harmless.
-rw-r--r--src/mcd-master.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/mcd-master.c b/src/mcd-master.c
index 29e9fbe8..9a468b0e 100644
--- a/src/mcd-master.c
+++ b/src/mcd-master.c
@@ -118,6 +118,10 @@ typedef struct {
gpointer userdata;
} McdAccountConnectionData;
+/* Used to poison 'default_master' when the object it points to is disposed.
+ * The default_master should basically be alive for the duration of the MC run.
+ */
+#define POISONED_MASTER ((McdMaster *) 0xdeadbeef)
static McdMaster *default_master = NULL;
@@ -425,6 +429,11 @@ _mcd_master_dispose (GObject * object)
priv->dispatcher = NULL;
g_object_unref (priv->proxy);
+ if (default_master == (McdMaster *) object)
+ {
+ default_master = POISONED_MASTER;
+ }
+
G_OBJECT_CLASS (mcd_master_parent_class)->dispose (object);
}
@@ -549,6 +558,9 @@ mcd_master_get_default (void)
{
if (!default_master)
default_master = MCD_MASTER (g_object_new (MCD_TYPE_MASTER, NULL));
+
+ g_return_val_if_fail (default_master != POISONED_MASTER, NULL);
+
return default_master;
}