return ret;
}
-int
-memdb_read(
- memdb_t *memdb,
- const char *path,
+// Original memdb_read without locking - Caller MUST handle the locking
+int
+memdb_read_nolock(
+ memdb_t *memdb,
+ const char *path,
gpointer *data_ret)
{
g_return_val_if_fail(memdb != NULL, -EINVAL);
g_return_val_if_fail(path != NULL, -EINVAL);
g_return_val_if_fail(data_ret != NULL, -EINVAL);
- memdb_tree_entry_t *te, *parent;
-
- g_mutex_lock (&memdb->mutex);
+ memdb_tree_entry_t *te, *parent;
if ((te = memdb_lookup_path(memdb, path, &parent))) {
if (te->type == DT_REG) {
*data_ret = g_memdup(te->data.value, te->size);
guint32 size = te->size;
- g_mutex_unlock (&memdb->mutex);
return size;
}
}
+ return -ENOENT;
+}
+
+int
+memdb_read(
+ memdb_t *memdb,
+ const char *path,
+ gpointer *data_ret)
+{
+ int res;
+ g_mutex_lock (&memdb->mutex);
+
+ res = memdb_read_nolock(memdb, path, data_ret);
+
g_mutex_unlock (&memdb->mutex);
- return -ENOENT;
+ return res;
}
static int
int res = 0;
GString *path = NULL;
+ // Prelock &memdb->mutex in order to enable the usage of memdb_read_nolock
+ // to prevent Deadlocks as in #2553
+ g_mutex_lock (&memdb->mutex);
g_mutex_lock (&mutex);
g_string_printf(str,"{\n");
if (!vminfo_to_path(vminfo, path)) goto err;
- int size = memdb_read(memdb, path->str, &tmp);
+ // use memdb_read_nolock because lock is handled here
+ int size = memdb_read_nolock(memdb, path->str, &tmp);
if (tmp == NULL) goto err;
if (size <= prop_len) goto ret;
g_free(tmp); // no-op if already null
tmp = NULL;
- int size = memdb_read(memdb, path->str, &tmp);
+ // use memdb_read_nolock because lock is handled here
+ int size = memdb_read_nolock(memdb, path->str, &tmp);
if (tmp == NULL || size <= prop_len) continue;
char *val = _get_property_value(tmp, size, prop, prop_len);
}
g_string_append_printf(str,"\n}\n");
g_mutex_unlock (&mutex);
-
+ g_mutex_unlock (&memdb->mutex);
return res;
err:
res = -EIO;