Skip to content

Commit

Permalink
resource: take a ref from iter to res only if res fully initialized
Browse files Browse the repository at this point in the history
The sid_resource_iter_create normally takes a reference to the resource.
However, we cannot take the ref if we are creating the iterator inside
resource's 'create' callback in which case we're actually creating an
iterator that is internal to the resource,. Such iterator would need
to be destroyed in resource's 'destroy' callback (causing the resource
to be unreffed). We would never get to that because the 'destroy' callback
is called only after the ref_count hits 0.

Currently, the only resource API function that takes a ref is the
sid_resource_iter_create, but the same would apply for any other API
function that could be called inside resource's create callback.
  • Loading branch information
prajnoha committed Sep 26, 2022
1 parent 9da9709 commit 860764e
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/resource/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ typedef struct sid_resource_iter {
struct list * prev; /* for safety */
struct list * current;
struct list * next; /* for safety */
bool res_refd : 1;
} sid_resource_iter_t;

typedef enum
Expand Down Expand Up @@ -1110,7 +1111,10 @@ sid_resource_iter_t *sid_resource_iter_create(sid_resource_t *res)
if (!(iter = malloc(sizeof(*iter))))
return NULL;

iter->res = sid_resource_ref(res);
if ((iter->res_refd = res->initialized))
iter->res = sid_resource_ref(res);
else
iter->res = res;

iter->current = &res->children;
iter->prev = iter->current->p;
Expand Down Expand Up @@ -1168,7 +1172,8 @@ void sid_resource_iter_reset(sid_resource_iter_t *iter)

void sid_resource_iter_destroy(sid_resource_iter_t *iter)
{
(void) sid_resource_unref(iter->res);
if (iter->res_refd)
(void) sid_resource_unref(iter->res);
free(iter);
}

Expand Down

0 comments on commit 860764e

Please sign in to comment.