From 4a3a7ca0b15485a9061017409b51fc5e4cf86ecb Mon Sep 17 00:00:00 2001 From: Amin Ben Romdhane Date: Thu, 24 Apr 2025 23:19:51 +0200 Subject: [PATCH] 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. --- libbbfdm-api/legacy/dmbbf.c | 12 +++++++----- libbbfdm-ubus/bbfdm-ubus.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/libbbfdm-api/legacy/dmbbf.c b/libbbfdm-api/legacy/dmbbf.c index d85fee2b..7fb1952c 100644 --- a/libbbfdm-api/legacy/dmbbf.c +++ b/libbbfdm-api/legacy/dmbbf.c @@ -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", ""); } } diff --git a/libbbfdm-ubus/bbfdm-ubus.c b/libbbfdm-ubus/bbfdm-ubus.c index 99c67345..b81160b5 100644 --- a/libbbfdm-ubus/bbfdm-ubus.c +++ b/libbbfdm-ubus/bbfdm-ubus.c @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -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; }