summaryrefslogtreecommitdiff
path: root/src/gclue-modem-gps.c
diff options
context:
space:
mode:
authorTeemu Ikonen <tpikonen@mailbox.org>2021-09-30 14:08:57 +0300
committerTeemu Ikonen <tpikonen@mailbox.org>2021-10-05 15:02:02 +0300
commit2d1968f84fa81426b1276efaa720956810915f81 (patch)
treee20cc53b494604588900adfd43841ecb431d4cc4 /src/gclue-modem-gps.c
parentd381d0ee71361eec4717ae6f739430880c1c25ec (diff)
downloadgeoclue-2d1968f84fa81426b1276efaa720956810915f81.tar.gz
location-source: Fix subclass resource leaks on start
The start_source() and stop_source() functions in GClueLocationSource are chained up by all the start() and stop() method implementations in GClueLocationSource subclasses to determine when to really start and stop the source and allocate / free the needed resources. Commit 0661107fe0 made start_source() return TRUE when the source was already active, which caused the resources already reserved for the physical source to be reserved again. The source class implementations are typically designed to hold just one set of resources, so the references to previously reserved resources are lost, that is they leak. An example of this is the GSocketClient reference (priv->client) held by GClueNMEASource. Another visible (in the debug log) example of the extra resources are callbacks connected to the "fix-*" signals of the physical sources (see gclue_modem_gps_start() for example). With more than one client using the same source, all clients receive the same location update N times, where N is the number of clients using the source. Make GClueLocationSource.start() and .stop() methods return enums GClueLocationSourceStartResult and GClueLocationSourceStopResult which gives subclasses more information on when to allocate resources on starting and stopping. The start_source() function now returns the value GCLUE_LOCATION_SOURCE_START_RESULT_ALREADY_STARTED when the source is already active. The subclass start() method implementations are changed to return immediately when they get this value from the base class. This effectively reverts the first diff in commit 0661107fe0 "location-source: Return source state from start_source and stop_source". The behaviour of stop() method subclass implementations remains the same. Freeing of resources is always attempted, except when the value GCLUE_LOCATION_SOURCE_STOP_RESULT_STILL_USED is returned from the base class.
Diffstat (limited to 'src/gclue-modem-gps.c')
-rw-r--r--src/gclue-modem-gps.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/src/gclue-modem-gps.c b/src/gclue-modem-gps.c
index 501c56e..53ea1b4 100644
--- a/src/gclue-modem-gps.c
+++ b/src/gclue-modem-gps.c
@@ -48,9 +48,9 @@ G_DEFINE_TYPE_WITH_CODE (GClueModemGPS,
GCLUE_TYPE_LOCATION_SOURCE,
G_ADD_PRIVATE (GClueModemGPS))
-static gboolean
+static GClueLocationSourceStartResult
gclue_modem_gps_start (GClueLocationSource *source);
-static gboolean
+static GClueLocationSourceStopResult
gclue_modem_gps_stop (GClueLocationSource *source);
static void
@@ -233,18 +233,20 @@ on_fix_gps (GClueModem *modem,
location);
}
-static gboolean
+static GClueLocationSourceStartResult
gclue_modem_gps_start (GClueLocationSource *source)
{
GClueLocationSourceClass *base_class;
GClueModemGPSPrivate *priv;
+ GClueLocationSourceStartResult base_result;
g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE);
priv = GCLUE_MODEM_GPS (source)->priv;
base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_modem_gps_parent_class);
- if (!base_class->start (source))
- return FALSE;
+ base_result = base_class->start (source);
+ if (base_result != GCLUE_LOCATION_SOURCE_START_RESULT_OK)
+ return base_result;
g_signal_connect (priv->modem,
"fix-gps",
@@ -257,21 +259,23 @@ gclue_modem_gps_start (GClueLocationSource *source)
on_gps_enabled,
source);
- return TRUE;
+ return base_result;
}
-static gboolean
+static GClueLocationSourceStopResult
gclue_modem_gps_stop (GClueLocationSource *source)
{
GClueModemGPSPrivate *priv = GCLUE_MODEM_GPS (source)->priv;
GClueLocationSourceClass *base_class;
GError *error = NULL;
+ GClueLocationSourceStopResult base_result;
g_return_val_if_fail (GCLUE_IS_LOCATION_SOURCE (source), FALSE);
base_class = GCLUE_LOCATION_SOURCE_CLASS (gclue_modem_gps_parent_class);
- if (!base_class->stop (source))
- return FALSE;
+ base_result = base_class->stop (source);
+ if (base_result == GCLUE_LOCATION_SOURCE_STOP_RESULT_STILL_USED)
+ return base_result;
g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modem),
G_CALLBACK (on_fix_gps),
@@ -286,5 +290,5 @@ gclue_modem_gps_stop (GClueLocationSource *source)
g_error_free (error);
}
- return TRUE;
+ return base_result;
}