feat(module.c, stk.c): expose dependency functions and integrate into init and poll

- Make stk_validate_dependencies and stk_topo_sort non static
- Add extern declarations in stk.c
- Run stk_validate_dependencies after module loads in stk_init
- Validation failure is fatal; unload all modules and return error code
- Run stk_topo_sort after validation, sort failure is logged but not fatal
- Add validate_deps label in stk_poll so all load/unload paths run validation
- Add dep error codes to stk_error_string
This commit is contained in:
2026-03-03 22:29:59 +01:00
parent 6faf33d944
commit ceb389de0d
2 changed files with 61 additions and 14 deletions
+2 -2
View File
@@ -156,7 +156,7 @@ int is_mod_loaded(const char *module_name)
return -1; return -1;
} }
static unsigned char stk_validate_dependencies(size_t count) unsigned char stk_validate_dependencies(size_t count)
{ {
size_t i, d; size_t i, d;
int found; int found;
@@ -183,7 +183,7 @@ static unsigned char stk_validate_dependencies(size_t count)
return STK_MOD_INIT_SUCCESS; return STK_MOD_INIT_SUCCESS;
} }
static unsigned char stk_topo_sort(size_t count, size_t *order) unsigned char stk_topo_sort(size_t count, size_t *order)
{ {
size_t *in_degree = NULL; size_t *in_degree = NULL;
size_t *queue = NULL; size_t *queue = NULL;
+59 -12
View File
@@ -56,6 +56,8 @@ unsigned char stk_module_init_memory(size_t capacity);
unsigned char stk_module_realloc_memory(size_t new_capacity); unsigned char stk_module_realloc_memory(size_t new_capacity);
void stk_module_unload(size_t index); void stk_module_unload(size_t index);
void stk_module_unload_all(void); void stk_module_unload_all(void);
unsigned char stk_validate_dependencies(size_t count);
unsigned char stk_topo_sort(size_t count, size_t *order);
static void build_path(char *dest, size_t dest_size, const char *dir, static void build_path(char *dest, size_t dest_size, const char *dir,
const char *file) const char *file)
@@ -77,6 +79,12 @@ static const char *stk_error_string(int error_code)
return "init failure"; return "init failure";
case STK_MOD_REALLOC_FAILURE: case STK_MOD_REALLOC_FAILURE:
return "memory reallocation failed"; return "memory reallocation failed";
case STK_MOD_DEP_NOT_FOUND_ERROR:
return "dependency not found";
case STK_MOD_DEP_VERSION_MISMATCH_ERROR:
return "dependency version mismatch";
case STK_MOD_DEP_CIRCULAR_ERROR:
return "circular dependency detected";
default: default:
return "unknown error"; return "unknown error";
} }
@@ -89,6 +97,8 @@ unsigned char stk_init(void)
char full_path[STK_PATH_MAX_OS]; char full_path[STK_PATH_MAX_OS];
char tmp_path[STK_PATH_MAX_OS]; char tmp_path[STK_PATH_MAX_OS];
int load_result; int load_result;
unsigned char dep_result;
size_t *order = NULL;
platform_mkdir(stk_mod_dir); platform_mkdir(stk_mod_dir);
build_path(stk_tmp_dir, sizeof(stk_tmp_dir), stk_mod_dir, stk_tmp_name); build_path(stk_tmp_dir, sizeof(stk_tmp_dir), stk_mod_dir, stk_tmp_name);
@@ -140,12 +150,31 @@ unsigned char stk_init(void)
} }
} }
if (successful_loads < file_count) { if (successful_loads < file_count)
stk_module_realloc_memory(successful_loads); stk_module_realloc_memory(successful_loads);
}
free(files); free(files);
if (module_count == 0)
goto scanned;
dep_result = stk_validate_dependencies(module_count);
if (dep_result != STK_MOD_INIT_SUCCESS) {
stk_log(STK_LOG_ERROR, "Dependency validation failed: %s",
stk_error_string(dep_result));
stk_module_unload_all();
return dep_result;
}
order = malloc(module_count * sizeof(size_t));
if (order) {
dep_result = stk_topo_sort(module_count, order);
if (dep_result != STK_MOD_INIT_SUCCESS)
stk_log(STK_LOG_ERROR, "Dependency sort failed: %s",
stk_error_string(dep_result));
free(order);
}
scanned: scanned:
watch_handle = platform_directory_watch_start(stk_mod_dir); watch_handle = platform_directory_watch_start(stk_mod_dir);
if (!watch_handle) { if (!watch_handle) {
@@ -199,6 +228,8 @@ size_t stk_poll(void)
int load_result; int load_result;
size_t successful_appends = 0; size_t successful_appends = 0;
char (*module_ids)[STK_MOD_ID_BUFFER] = NULL; char (*module_ids)[STK_MOD_ID_BUFFER] = NULL;
unsigned char dep_result;
size_t *order = NULL;
if (module_count > 0) { if (module_count > 0) {
module_ids = malloc(module_count * sizeof(*module_ids)); module_ids = malloc(module_count * sizeof(*module_ids));
@@ -276,9 +307,8 @@ size_t stk_poll(void)
handle_grow: handle_grow:
remaining_loads = load_count - unload_count; remaining_loads = load_count - unload_count;
new_capacity = module_count + remaining_loads; new_capacity = module_count + remaining_loads;
if (stk_module_realloc_memory(new_capacity) != STK_MOD_INIT_SUCCESS) { if (stk_module_realloc_memory(new_capacity) != STK_MOD_INIT_SUCCESS)
goto free_poll; goto free_poll;
}
begin_operations: begin_operations:
for (i = 0; i < unload_count; ++i) for (i = 0; i < unload_count; ++i)
@@ -303,12 +333,11 @@ begin_operations:
} }
load_result = stk_module_load(tmp_path, mod_index); load_result = stk_module_load(tmp_path, mod_index);
if (load_result != STK_MOD_INIT_SUCCESS) { if (load_result != STK_MOD_INIT_SUCCESS)
stk_log(STK_LOG_ERROR, "Failed to reload module %s: %s", stk_log(STK_LOG_ERROR, "Failed to reload module %s: %s",
file_list[file_index], file_list[file_index],
stk_error_string(load_result)); stk_error_string(load_result));
} }
}
holes_to_fill = (load_count < unload_count) ? load_count : unload_count; holes_to_fill = (load_count < unload_count) ? load_count : unload_count;
for (i = 0; i < holes_to_fill; ++i) { for (i = 0; i < holes_to_fill; ++i) {
@@ -328,12 +357,11 @@ begin_operations:
} }
load_result = stk_module_load(tmp_path, target_index); load_result = stk_module_load(tmp_path, target_index);
if (load_result != STK_MOD_INIT_SUCCESS) { if (load_result != STK_MOD_INIT_SUCCESS)
stk_log(STK_LOG_ERROR, "Failed to load module %s: %s", stk_log(STK_LOG_ERROR, "Failed to load module %s: %s",
file_list[file_index], file_list[file_index],
stk_error_string(load_result)); stk_error_string(load_result));
} }
}
if (load_count > unload_count) if (load_count > unload_count)
goto append_modules; goto append_modules;
@@ -341,7 +369,7 @@ begin_operations:
if (unload_count > load_count) if (unload_count > load_count)
goto trim_arrays; goto trim_arrays;
goto free_poll; goto validate_deps;
append_modules: append_modules:
for (; i < load_count; ++i) { for (; i < load_count; ++i) {
@@ -372,11 +400,10 @@ append_modules:
module_count += successful_appends; module_count += successful_appends;
if (successful_appends < (load_count - holes_to_fill)) { if (successful_appends < (load_count - holes_to_fill))
stk_module_realloc_memory(module_count); stk_module_realloc_memory(module_count);
}
goto free_poll; goto validate_deps;
trim_arrays: trim_arrays:
write_pos = unloaded_mod_indices[holes_to_fill]; write_pos = unloaded_mod_indices[holes_to_fill];
@@ -395,6 +422,26 @@ trim_arrays:
module_count = write_pos; module_count = write_pos;
stk_module_realloc_memory(module_count); stk_module_realloc_memory(module_count);
validate_deps:
if (module_count == 0)
goto free_poll;
dep_result = stk_validate_dependencies(module_count);
if (dep_result != STK_MOD_INIT_SUCCESS) {
stk_log(STK_LOG_ERROR, "Dependency validation failed: %s",
stk_error_string(dep_result));
goto free_poll;
}
order = malloc(module_count * sizeof(size_t));
if (order) {
dep_result = stk_topo_sort(module_count, order);
if (dep_result != STK_MOD_INIT_SUCCESS)
stk_log(STK_LOG_ERROR, "Dependency sort failed: %s",
stk_error_string(dep_result));
free(order);
}
free_poll: free_poll:
free(reloaded_mod_indices); free(reloaded_mod_indices);
free(reloaded_mod_file_indices); free(reloaded_mod_file_indices);