From 44103038c0fa02c75147eb44cd1d3169f4445833 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 26 Oct 2026 08:45:46 +0100 Subject: [PATCH] Preserve selected global log path and verify database owner reload --- src/utun_instance.c | 2 +- tests/test_instance_contract.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/utun_instance.c b/src/utun_instance.c index 41086941..ed354ce5 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -371,7 +371,7 @@ struct UTUN_INSTANCE* utun_instance_create_from_config(struct UASYNC* ua, struct DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "instance create requires uasync and config"); return NULL; } - if (config->global.log_file[0]) { + if (config->global.log_file[0] && !g_debug_config.file_output) { snprintf(g_config_log_path, sizeof(g_config_log_path), "%s", config->global.log_file); debug_set_output_file(g_config_log_path); } diff --git a/tests/test_instance_contract.c b/tests/test_instance_contract.c index 8c4a5b89..e0fa3797 100644 --- a/tests/test_instance_contract.c +++ b/tests/test_instance_contract.c @@ -202,13 +202,42 @@ static void test_headless(struct UASYNC* ua) { DEBUG_INFO(DEBUG_CATEGORY_SYS, "PASS chat-only lifecycle: three headless ports/clients, timer faults, retained SQLite and malformed binds"); } +static void test_database_and_logger(struct UASYNC* ua) { + char root[] = "/tmp/utun-instance-owners-XXXXXX"; assert(mkdtemp(root)); + char path[256], db_a[256], db_b[256], log_a[256], log_b[256], extras[1024], file[512]; + snprintf(path, sizeof(path), "%s/config", root); snprintf(db_a, sizeof(db_a), "%s/one/deep", root); + snprintf(db_b, sizeof(db_b), "%s/two", root); snprintf(log_a, sizeof(log_a), "%s/first.log", root); + snprintf(log_b, sizeof(log_b), "%s/second.log", root); + snprintf(extras, sizeof(extras), "[global]\ndb_path=%s\nlog_file=%s\n", db_a, log_a); + write_config(path, "same owner", "", extras); + struct UTUN_INSTANCE* inst = utun_instance_create(ua, path); assert(inst && !inst->core_started); + snprintf(file, sizeof(file), "%s/chats.db", db_a); + assert(!strcmp(sqlite3_db_filename(inst->topo_sqlite_db, "main"), file)); + assert(sqlite3_exec(inst->topo_sqlite_db, "CREATE TABLE instance_contract(value); INSERT INTO instance_contract VALUES(7)", + NULL, NULL, NULL) == SQLITE_OK); + snprintf(extras, sizeof(extras), "[global]\ndb_path=%s\nlog_file=%s\n", db_b, log_b); + write_config(path, "same owner", "", extras); + inst = utun_instance_reload(inst, ua, path); assert(inst && !inst->core_started && !inst->running); + snprintf(file, sizeof(file), "%s/chats.db", db_b); + assert(!strcmp(sqlite3_db_filename(inst->topo_sqlite_db, "main"), file)); + assert(!strcmp(g_debug_config.output_file, log_a)); // уже открытый общий logger сохраняет первый путь + utun_instance_destroy(inst); + assert(!strcmp(g_debug_config.output_file, log_a) && !debug_reopen_log()); // config освобождён, путь остаётся жив + debug_disable_file_output(); + snprintf(file, sizeof(file), "%s/chats.db", db_a); assert(!unlink(file)); + snprintf(file, sizeof(file), "%s/chats.db", db_b); assert(!unlink(file)); + assert(!unlink(path) && !unlink(log_a) && !rmdir(db_a) && !rmdir(db_b)); + snprintf(file, sizeof(file), "%s/one", root); assert(!rmdir(file) && !rmdir(root)); + DEBUG_INFO(DEBUG_CATEGORY_SYS, "PASS db_path restart, recursive directory, stopped state and logger path after config destruction"); +} + int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_SYS, DEBUG_LEVEL_INFO); debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO); test_callbacks(); size_t baseline = u_get_allocated_count(); struct UASYNC* ua = uasync_create(); assert(ua); - test_creation(ua); test_reload(ua); test_headless(ua); + test_creation(ua); test_reload(ua); test_headless(ua); test_database_and_logger(ua); uasync_poll(ua, 0); // удалённые heap-таймеры освобождаются при следующем poll debug_set_category_level(DEBUG_CATEGORY_SYS, DEBUG_LEVEL_INFO); uasync_print_resources(ua, "instance contract before owner destroy");