Skip to content

Commit

Permalink
rpmKeyring and rpmstrPool nrefs to atomic_int
Browse files Browse the repository at this point in the history
These data structures use the content lock (aka mutex) to also protect the
reference counter. This is wrong and complicates freeing interconnected
data structures. This lock should only protect the content of the
instance.

Turn nrefs members into atomic_int so they are thread-save themselves.

Make sure to only use ++ and -- operators and avoid non atomic
combinations of reading and writing.  As the nref can't change again
after reaching zero this is thread-save even as we look at the result
an instruction later.

Make sure the data lock is not aquired for updating the nrefs members.

Technically the *Free() functions should *Link() the instance after the
ref count has reached 0 and the decision to free it has been made.
Otherwise the cleanup code linking and freeing to will lead to a
recusions. This is not neccessary here so it is omitted.
  • Loading branch information
ffesti authored and dmnks committed Oct 15, 2024
1 parent 4fc21ff commit 87aad15
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 43 deletions.
41 changes: 15 additions & 26 deletions rpmio/rpmkeyring.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "system.h"

#include <mutex>
#include <atomic>
#include <vector>
#include <shared_mutex>
#include <string>
Expand All @@ -22,7 +23,7 @@ struct rpmPubkey_s {
std::string keyid;
rpmPubkey primarykey;
pgpDigParams pgpkey;
int nrefs;
std::atomic_int nrefs;
std::shared_mutex mutex;
};

Expand All @@ -31,7 +32,7 @@ using rdlock = std::shared_lock<std::shared_mutex>;

struct rpmKeyring_s {
std::map<std::string,rpmPubkey> keys; /* pointers to keys */
int nrefs;
std::atomic_int nrefs;
std::shared_mutex mutex;
};

Expand All @@ -56,15 +57,13 @@ rpmKeyring rpmKeyringNew(void)

rpmKeyring rpmKeyringFree(rpmKeyring keyring)
{
if (keyring == NULL)
if (keyring == NULL || --keyring->nrefs > 0)
return NULL;

wrlock lock(keyring->mutex);
if (--keyring->nrefs == 0) {
for (auto & item : keyring->keys)
rpmPubkeyFree(item.second);
delete keyring;
}
for (auto & item : keyring->keys)
rpmPubkeyFree(item.second);
delete keyring;

return NULL;
}

Expand Down Expand Up @@ -159,7 +158,6 @@ rpmPubkey rpmKeyringLookupKey(rpmKeyring keyring, rpmPubkey key)
rpmKeyring rpmKeyringLink(rpmKeyring keyring)
{
if (keyring) {
wrlock lock(keyring->mutex);
keyring->nrefs++;
}
return keyring;
Expand Down Expand Up @@ -219,12 +217,6 @@ static rpmPubkey rpmPubkeyNewSubkey(rpmPubkey primarykey, pgpDigParams pgpkey)
return key;
}

static rpmPubkey pubkeyLink(rpmPubkey key)
{
key->nrefs++;
return key;
}

rpmPubkey *rpmGetSubkeys(rpmPubkey primarykey, int *count)
{
rpmPubkey *subkeys = NULL;
Expand All @@ -243,7 +235,7 @@ rpmPubkey *rpmGetSubkeys(rpmPubkey primarykey, int *count)
subkeys = (rpmPubkey *)xmalloc(pgpsubkeysCount * sizeof(*subkeys));
for (i = 0; i < pgpsubkeysCount; i++) {
subkeys[i] = rpmPubkeyNewSubkey(primarykey, pgpsubkeys[i]);
primarykey = pubkeyLink(primarykey);
primarykey = rpmPubkeyLink(primarykey);
}
free(pgpsubkeys);
}
Expand All @@ -259,7 +251,7 @@ rpmPubkey pubkeyPrimarykey(rpmPubkey key)
if (key) {
wrlock lock(key->mutex);
if (key->primarykey == NULL) {
primarykey = pubkeyLink(key);
primarykey = rpmPubkeyLink(key);
} else {
primarykey = rpmPubkeyLink(key->primarykey);
}
Expand Down Expand Up @@ -301,22 +293,19 @@ char * rpmPubkeyKeyIDAsHex(rpmPubkey key)

rpmPubkey rpmPubkeyFree(rpmPubkey key)
{
if (key == NULL)
if (key == NULL || --key->nrefs > 0)
return NULL;

wrlock lock(key->mutex);
if (--key->nrefs == 0) {
pgpDigParamsFree(key->pgpkey);
rpmPubkeyFree(key->primarykey);
delete key;
}
pgpDigParamsFree(key->pgpkey);
rpmPubkeyFree(key->primarykey);
delete key;

return NULL;
}

rpmPubkey rpmPubkeyLink(rpmPubkey key)
{
if (key) {
wrlock lock(key->mutex);
key->nrefs++;
}
return key;
Expand Down
31 changes: 14 additions & 17 deletions rpmio/rpmstrpool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <shared_mutex>
#include <mutex>
#include <atomic>

#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -43,7 +44,7 @@ struct rpmstrPool_s {

poolHash hash; /* string -> sid hash table */
int frozen; /* are new id additions allowed? */
int nrefs; /* refcount */
std::atomic_int nrefs; /* refcount */
std::shared_mutex mutex;
};

Expand Down Expand Up @@ -256,29 +257,25 @@ rpmstrPool rpmstrPoolCreate(void)

rpmstrPool rpmstrPoolFree(rpmstrPool pool)
{
if (pool) {
wrlock lock(pool->mutex);
if (pool->nrefs > 1) {
pool->nrefs--;
} else {
if (pool_debug)
poolHashPrintStats(pool);
poolHashFree(pool->hash);
free(pool->offs);
for (int i=1;i<=pool->chunks_size;i++) {
pool->chunks[i] = _free(pool->chunks[i]);
}
free(pool->chunks);
free(pool);
}
if (pool == NULL || --pool->nrefs > 0)
return NULL;

if (pool_debug)
poolHashPrintStats(pool);
poolHashFree(pool->hash);
free(pool->offs);
for (int i=1; i<=pool->chunks_size; i++) {
pool->chunks[i] = _free(pool->chunks[i]);
}
free(pool->chunks);
free(pool);

return NULL;
}

rpmstrPool rpmstrPoolLink(rpmstrPool pool)
{
if (pool) {
wrlock lock(pool->mutex);
pool->nrefs++;
}
return pool;
Expand Down

0 comments on commit 87aad15

Please sign in to comment.