summaryrefslogtreecommitdiff
path: root/resource.c
diff options
context:
space:
mode:
authorRussell King <rmk@armlinux.org.uk>2021-09-11 13:57:42 +0100
committerRussell King <rmk@armlinux.org.uk>2021-09-11 13:57:42 +0100
commit2f45bcf78b77193ad6107fbb92ad0f93eb1ad4fc (patch)
tree18b115356a92e67e2276a2dbe97139d2237c0f24 /resource.c
parentacc52e700121120726b42a6dadd8c12f030ba349 (diff)
Restrict updates to the newest updater
Prevent old update connections from providing updates, closing them if they attempt an update. In doing so, this also limits resource usage when we have multiple updaters connected (which should never happen.) Signed-off-by: Russell King <rmk@armlinux.org.uk>
Diffstat (limited to 'resource.c')
-rw-r--r--resource.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/resource.c b/resource.c
index bc5dfdd..8c67635 100644
--- a/resource.c
+++ b/resource.c
@@ -73,6 +73,20 @@ static int object_v1_get(struct client *c, struct resource *r)
return 1;
}
+static void object_v1_close(struct client *c, struct resource *r)
+{
+ struct resource_object *obj = r->data;
+
+ // Remove this client from the object list
+ resource_obj_del_client(obj, c);
+}
+
+static void object_v1_update_open(struct client *c, struct resource *r)
+{
+ // Keep track of the latest updater
+ r->updater = c;
+}
+
// Update all attached clients with the new resource object data
static int object_v1_update(struct client *c, struct resource *r, const char *m)
{
@@ -80,6 +94,12 @@ static int object_v1_update(struct client *c, struct resource *r, const char *m)
GString *string;
char *n;
+ // Only allow the latest updater to provide updates, in case we
+ // end up with multiple connections. This also allows us to quickly
+ // release the resources of a stale connection.
+ if (r->updater != c)
+ return -1;
+
// Remove any trailing whitespace.
n = g_strchomp(g_strdup(m));
@@ -97,18 +117,20 @@ static int object_v1_update(struct client *c, struct resource *r, const char *m)
return 0;
}
-static void object_v1_close(struct client *c, struct resource *r)
+static void object_v1_update_close(struct client *c, struct resource *r)
{
- struct resource_object *obj = r->data;
-
- // Remove this client from the object list
- resource_obj_del_client(obj, c);
+ // If the updater goes away, clear the data so we don't serve
+ // stale data.
+ if (r->updater == c)
+ r->updater = NULL;
}
static const struct resource_ops resource_v1_ops = {
.get = object_v1_get,
- .update = object_v1_update,
.close = object_v1_close,
+ .update_open = object_v1_update_open,
+ .update = object_v1_update,
+ .update_close = object_v1_update_close,
};
static struct resource resource_position1 = {