Reference DB: add file lock to prevent race condition when updating reference DB file

Added an exclusive file locking mechanism using `flock()` to ensure that
only one process at a time can update the '/var/state/bbfdm_reference_db' file.
This prevents data loss or corruption caused by concurrent access.

This change improves robustness when `bbfdm_refresh_references()` is called
by multiple processes in parallel.
This commit is contained in:
Amin Ben Romdhane 2025-04-24 23:19:51 +02:00
parent ab5cde2c42
commit 4a3a7ca0b1
2 changed files with 42 additions and 5 deletions

View file

@ -1921,24 +1921,26 @@ static void create_required_sections(struct dmctx *ctx)
dmuci_rename_section_by_section(ref_s, ctx->in_value);
} else {
struct uci_list *uci_list = NULL;
struct uci_element *e = NULL, *tmp = NULL;
struct uci_element *e = NULL;
dmuci_get_value_by_section_list(ref_s, "reference_path", &uci_list);
if (uci_list != NULL) {
uci_foreach_element_safe(uci_list, tmp, e) {
uci_foreach_element(uci_list, e) {
dmuci_set_value_varstate("bbfdm_reference_db", "reference_path", e->name, "");
dmuci_del_list_value_by_section(ref_s, "reference_path", e->name);
}
dmuci_set_value_by_section_varstate(ref_s, "reference_path", "");
}
dmuci_get_value_by_section_list(ref_s, "reference_value", &uci_list);
if (uci_list != NULL) {
uci_foreach_element_safe(uci_list, tmp, e) {
uci_foreach_element(uci_list, e) {
dmuci_set_value_varstate("bbfdm_reference_db", "reference_value", e->name, "");
dmuci_del_list_value_by_section(ref_s, "reference_value", e->name);
}
dmuci_set_value_by_section_varstate(ref_s, "reference_value", "");
}
}

View file

@ -12,6 +12,9 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/file.h>
#include <libubox/blobmsg.h>
#include <libubox/uloop.h>
#include <libubus.h>
@ -779,6 +782,33 @@ void bbfdm_ubus_load_data_model(DM_MAP_OBJ *DynamicObj)
INTERNAL_ROOT_TREE = DynamicObj;
}
static int bbfdm_lock_reference_db(void)
{
#define BBF_LOCK_FILE "/var/lock/bbfdm_reference_db.lock"
int fd = open(BBF_LOCK_FILE, O_CREAT | O_RDWR, 0666);
if (fd == -1) {
BBF_ERR("Error opening lock file %s: %s", BBF_LOCK_FILE, strerror(errno));
return -1;
}
if (flock(fd, LOCK_EX) == -1) {
BBF_ERR("Error locking file %s: %s", BBF_LOCK_FILE, strerror(errno));
close(fd);
return -1;
}
return fd; // Lock held
}
static void bbfdm_unlock_reference_db(int lock_fd)
{
if (lock_fd >= 0) {
flock(lock_fd, LOCK_UN);
close(lock_fd);
}
}
int bbfdm_refresh_references(unsigned int dm_type, const char *srv_obj_name)
{
char hash_str[9] = {0};
@ -791,6 +821,10 @@ int bbfdm_refresh_references(unsigned int dm_type, const char *srv_obj_name)
.dm_type = dm_type
};
int lock_fd = bbfdm_lock_reference_db();
if (lock_fd == -1)
return -1;
bbf_init(&bbf_ctx);
int res = bbfdm_cmd_exec(&bbf_ctx, BBF_REFERENCES_DB);
@ -804,6 +838,7 @@ int bbfdm_refresh_references(unsigned int dm_type, const char *srv_obj_name)
}
bbf_cleanup(&bbf_ctx);
bbfdm_unlock_reference_db(lock_fd);
return res;
}