chatgui: диагностика воспроизведения голосовых сообщений (Windows)
- sound_manager: ma_engine_init/playRawPcm логируют через DEBUG_* (qWarning/qDebug терялись в GUI-приложении без консоли); детальный результат старта PCM (rc/is_playing/cursor) - main: ранняя инициализация лога в GUI-потоке до SoundManager::init, чтобы диагностика инициализации попала в файл - messagedelegate: лог клика по Play/timeline (filePath/dlState/существует ли файл) - voiceplayback: лог заголовка opus (sr/ch/frameSamples) Попутные правки: - u_async: фикс двойного close wakeup_pipe (eventfd/Windows) - chat_core: NULL-guard в get_db/is_initialized - android: sqlite открывается в utun_instance_init, cleanup stale-потока без утечки fd - android SettingsScreen: компактная раскладка имени интерфейса
This commit is contained in:
1 parent
19dc076528
commit
9793733cd5
8 files changed
+76
-51
No files matched your search
@@ -249,8 +249,6 @@ private fun GeneralSettingsTab(vm: ChatViewModel, dirty: Boolean, onDirty: (Bool
|
||||
val stateColor = when (s.state) { 2 -> Color(0xFF27AE60); 1 -> Color(0xFFF1C40F); else -> Color(0xFFE53935) }
|
||||
Column(modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(s.ifName, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.weight(1f))
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Text("${s.bindIp}:${s.port}", color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodySmall)
|
||||
Spacer(Modifier.width(6.dp))
|
||||
Surface(shape = MaterialTheme.shapes.extraSmall, color = stateColor,
|
||||
@@ -265,6 +263,8 @@ private fun GeneralSettingsTab(vm: ChatViewModel, dirty: Boolean, onDirty: (Bool
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
}
|
||||
}
|
||||
Text(s.ifName, style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.fillMaxWidth())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +261,8 @@ static void install_crash_handlers(void) {
|
||||
static void* instance_thread(void* arg) {
|
||||
char* config_text = (char*)arg;
|
||||
int my_gen = g_generation;
|
||||
struct UASYNC* my_ua = NULL; /* поток-локальная копия — для cleanup stale-потока */
|
||||
struct UTUN_INSTANCE* my_inst = NULL;
|
||||
|
||||
struct utun_config* config = parse_config_from_buf(config_text, strlen(config_text), "android");
|
||||
u_free(config_text);
|
||||
@@ -269,6 +271,7 @@ static void* instance_thread(void* arg) {
|
||||
install_crash_handlers();
|
||||
|
||||
g_ua = uasync_create();
|
||||
my_ua = g_ua;
|
||||
if (!g_ua) { IL_LOGE("uasync_create failed"); free_config(config); __atomic_store_n(&g_thread_running, 0, __ATOMIC_RELEASE); pthread_detach(pthread_self()); return NULL; }
|
||||
standby_init(g_ua);
|
||||
|
||||
@@ -280,6 +283,7 @@ static void* instance_thread(void* arg) {
|
||||
ensure_keys(config);
|
||||
|
||||
g_inst = utun_instance_create_from_config(g_ua, config);
|
||||
my_inst = g_inst;
|
||||
if (!g_inst) {
|
||||
IL_LOGE("utun_instance_create_from_config failed");
|
||||
standby_deinit();
|
||||
@@ -294,25 +298,8 @@ static void* instance_thread(void* arg) {
|
||||
|
||||
IL_LOGI("instance created, node_id=0x%016llx", (unsigned long long)g_inst->node_id);
|
||||
|
||||
/* Open shared SQLite DB */
|
||||
if (g_db_path[0] && !g_inst->topo_sqlite_db) {
|
||||
char db_file[512];
|
||||
snprintf(db_file, sizeof(db_file), "%s/chats.db", g_db_path);
|
||||
int rc = sqlite3_open_v2(db_file, &g_inst->topo_sqlite_db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL);
|
||||
if (rc == SQLITE_OK && g_inst->topo_sqlite_db) {
|
||||
sqlite3_exec(g_inst->topo_sqlite_db, "PRAGMA journal_mode=WAL", NULL, NULL, NULL);
|
||||
sqlite3_exec(g_inst->topo_sqlite_db, "PRAGMA foreign_keys=ON", NULL, NULL, NULL);
|
||||
sqlite3_exec(g_inst->topo_sqlite_db, "PRAGMA synchronous=NORMAL", NULL, NULL, NULL);
|
||||
sqlite3_exec(g_inst->topo_sqlite_db, "PRAGMA wal_autocheckpoint=10000", NULL, NULL, NULL);
|
||||
topo_node_sqlite_init(g_inst->topo_sqlite_db);
|
||||
IL_LOGI("SQLite opened %s", db_file);
|
||||
} else {
|
||||
IL_LOGE("SQLite open failed rc=%d", rc);
|
||||
if (g_inst->topo_sqlite_db) { sqlite3_close(g_inst->topo_sqlite_db); g_inst->topo_sqlite_db = NULL; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Shared SQLite DB открывается внутри utun_instance_init() → topo_groups_init()
|
||||
(topo_group.c). Двойное открытие здесь давало утечку соединения на каждый рестарт. */
|
||||
/* Full init: db_sync, chat_core, chat_sync, init_connections */
|
||||
if (utun_instance_init(g_inst) != 0) {
|
||||
IL_LOGE("utun_instance_init failed");
|
||||
@@ -369,13 +356,17 @@ static void* instance_thread(void* arg) {
|
||||
g_inst ? g_inst->connections : NULL);
|
||||
uasync_mark_stopped(g_ua);
|
||||
__atomic_store_n(&g_running, 0, __ATOMIC_RELEASE);
|
||||
utun_instance_destroy(g_inst);
|
||||
struct UTUN_INSTANCE* old_inst = g_inst;
|
||||
g_inst = NULL;
|
||||
utun_instance_destroy(old_inst);
|
||||
my_inst = NULL;
|
||||
uasync_print_resources(g_ua, "AFTER_DESTROY");
|
||||
u_report_unfreed_blocks();
|
||||
standby_deinit();
|
||||
uasync_destroy(g_ua, 0);
|
||||
my_ua = NULL;
|
||||
g_ua = uasync_create();
|
||||
my_ua = g_ua;
|
||||
if (!g_ua) { IL_LOGE("poll exit: uasync_create failed"); break; }
|
||||
standby_init(g_ua);
|
||||
|
||||
@@ -389,20 +380,11 @@ static void* instance_thread(void* arg) {
|
||||
if (!config) { IL_LOGE("poll exit: parse_config failed"); break; }
|
||||
|
||||
g_inst = utun_instance_create_from_config(g_ua, config);
|
||||
my_inst = g_inst;
|
||||
if (!g_inst) { IL_LOGE("poll exit: create_from_config failed"); break; }
|
||||
chat_event_set_handler(g_inst, chat_event_forward);
|
||||
|
||||
char db_file[512];
|
||||
snprintf(db_file, sizeof(db_file), "%s/chats.db", g_db_path);
|
||||
int rc = sqlite3_open_v2(db_file, &g_inst->topo_sqlite_db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL);
|
||||
if (rc == SQLITE_OK && g_inst->topo_sqlite_db) {
|
||||
sqlite3_exec(g_inst->topo_sqlite_db, "PRAGMA journal_mode=WAL", NULL, NULL, NULL);
|
||||
sqlite3_exec(g_inst->topo_sqlite_db, "PRAGMA foreign_keys=ON", NULL, NULL, NULL);
|
||||
sqlite3_exec(g_inst->topo_sqlite_db, "PRAGMA synchronous=NORMAL", NULL, NULL, NULL);
|
||||
topo_node_sqlite_init(g_inst->topo_sqlite_db);
|
||||
} else { IL_LOGE("poll exit: SQLite open failed rc=%d", rc); break; }
|
||||
|
||||
/* Shared SQLite DB открывается внутри utun_instance_init() (topo_group.c). */
|
||||
if (utun_instance_init(g_inst) != 0) { IL_LOGE("poll exit: utun_instance_init failed"); break; }
|
||||
chat_core_sync_my_addresses(g_inst);
|
||||
fire_local_sockets_event();
|
||||
@@ -424,22 +406,29 @@ static void* instance_thread(void* arg) {
|
||||
|
||||
if (my_gen == g_generation) {
|
||||
__atomic_store_n(&g_running, 0, __ATOMIC_RELEASE);
|
||||
if (g_inst) {
|
||||
chat_event_post(g_inst, CHAT_EVT_SERVICE_STOPPED, NULL, 0);
|
||||
utun_instance_destroy(g_inst);
|
||||
if (my_inst) {
|
||||
chat_event_post(my_inst, CHAT_EVT_SERVICE_STOPPED, NULL, 0);
|
||||
g_inst = NULL;
|
||||
utun_instance_destroy(my_inst);
|
||||
my_inst = NULL;
|
||||
}
|
||||
if (g_ua) {
|
||||
if (my_ua) {
|
||||
standby_deinit();
|
||||
uasync_destroy(g_ua, 0);
|
||||
uasync_destroy(my_ua, 0);
|
||||
g_ua = NULL;
|
||||
my_ua = NULL;
|
||||
}
|
||||
char* stale_cfg = (char*)__atomic_exchange_n(&g_restart_config, NULL, __ATOMIC_ACQUIRE);
|
||||
u_free(stale_cfg);
|
||||
u_report_unfreed_blocks();
|
||||
IL_LOGI("cleanup complete (gen=%d)", my_gen);
|
||||
} else {
|
||||
IL_LOGI("cleanup skipped — thread gen=%d but current gen=%d (stale thread)", my_gen, g_generation);
|
||||
/* stale-поток: глобальные g_inst/g_ua уже принадлежат новому потоку,
|
||||
но собственные объекты этого потока надо закрыть, иначе течёт fd. */
|
||||
IL_LOGI("cleanup (stale thread gen=%d vs %d): destroying own inst=%p ua=%p to avoid fd leak",
|
||||
my_gen, g_generation, (void*)my_inst, (void*)my_ua);
|
||||
if (my_inst) { utun_instance_destroy(my_inst); my_inst = NULL; }
|
||||
if (my_ua) { uasync_destroy(my_ua, 0); my_ua = NULL; }
|
||||
}
|
||||
__atomic_store_n(&g_thread_running, 0, __ATOMIC_RELEASE);
|
||||
pthread_mutex_lock(&g_stop_mutex);
|
||||
|
||||
Reference in new issue
Block a user