From 72ee8f25864c3ddee139a3cf9b998c8cf63fca85 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 29 Oct 2026 11:51:07 +0100 Subject: [PATCH] Release detached voice and PM file payloads when queued work is cancelled --- .../jni_bridge/android_jni_bridge.c | 22 +++++++++++-------- .../libutun_lite/voice_recorder.c | 15 ++++++------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/tools/chatgui-android/jni_bridge/android_jni_bridge.c b/tools/chatgui-android/jni_bridge/android_jni_bridge.c index 0ba5e660..f2fc56c2 100644 --- a/tools/chatgui-android/jni_bridge/android_jni_bridge.c +++ b/tools/chatgui-android/jni_bridge/android_jni_bridge.c @@ -719,9 +719,15 @@ void utun_bridge_dm_request_messages(const char* conv_id, uint64_t generation) { bridge_post_request(dm_messages_trampoline, req, &req->inst); } +static void dm_file_discard(void* arg) { + struct dm_file_req* req = arg; + if (req->remove_source && remove(req->path) && errno != ENOENT) + bridge_log(BLEV_WARN, "DM file cancellation cleanup failed path=%s errno=%d: %s", req->path, errno, strerror(errno)); + u_free(req); +} + int utun_bridge_dm_send_file(const char* conv_id, const char* path, const char* name, uint64_t generation, uint64_t request_id) { - struct UASYNC* ua = instance_lite_get_uasync(); - if (!conv_id || !path || !name || !generation || !request_id || !uasync_is_running(ua)) { + if (!conv_id || !path || !name || !generation || !request_id || !instance_lite_is_running()) { bridge_log(BLEV_WARN, "DM file: invalid request/core stopped"); return -1; } struct dm_file_req* req = u_calloc(1, sizeof(*req)); @@ -738,10 +744,9 @@ int utun_bridge_dm_send_file(const char* conv_id, const char* path, const char* req->remove_source = 1; /* PM picker передаёт собственный уникальный cache-файл. */ snprintf(req->info.name, sizeof(req->info.name), "%s", name); if (attachment_validate(&req->info)) { bridge_log(BLEV_ERROR, "DM file: invalid name"); u_free(req); return -1; } - struct posted_task* post = u_calloc(1, sizeof(*post)); - if (!post) { bridge_log(BLEV_ERROR, "DM file: completion allocation failed"); u_free(req); return -1; } - post->callback = dm_send_file_trampoline; post->arg = req; - uasync_post_reserved(ua, post); + if (instance_lite_post(dm_send_file_trampoline, req, &req->inst, dm_file_discard)) { + bridge_log(BLEV_WARN, "DM file: worker rejected request=%llu", (unsigned long long)request_id); u_free(req); return -1; + } return 0; } @@ -1368,9 +1373,8 @@ static void bridge_notify_network_active_trampoline(void* arg) { } void utun_bridge_notify_network_active(void) { - struct UASYNC* ua = instance_lite_get_uasync(); - if (!ua) return; - uasync_post(ua, bridge_notify_network_active_trampoline, NULL); + if (instance_lite_post(bridge_notify_network_active_trampoline, NULL, NULL, NULL)) + bridge_log(BLEV_DEBUG, "Network activity notification rejected: core not ready"); } void utun_bridge_collect_conn_list(void) { diff --git a/tools/chatgui-android/libutun_lite/voice_recorder.c b/tools/chatgui-android/libutun_lite/voice_recorder.c index a2fc0432..d2d75819 100644 --- a/tools/chatgui-android/libutun_lite/voice_recorder.c +++ b/tools/chatgui-android/libutun_lite/voice_recorder.c @@ -207,12 +207,10 @@ int voice_recorder_stop(int* out_duration_ms) { } int duration = (int)(now_ms() - g_rec->start_time_ms); if (out_duration_ms) *out_duration_ms = duration; - struct UASYNC* ua = instance_lite_get_uasync(); struct attachment_send_req* req = u_calloc(1, sizeof(*req)); - struct posted_task* post = u_calloc(1, sizeof(*post)); - if (!uasync_is_running(ua) || !req || !post || duration < 500) { - DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "voice stop: discarded duration=%d core=%d allocated=%d", duration, uasync_is_running(ua), !!req && !!post); - u_free(req); u_free(post); voice_cleanup_locked(g_rec); + if (!instance_lite_is_running() || !req || duration < 500) { + DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "voice stop: discarded duration=%d core=%d allocated=%d", duration, instance_lite_is_running(), !!req); + u_free(req); voice_cleanup_locked(g_rec); pthread_mutex_unlock(&g_rec->mtx); pthread_mutex_unlock(&g_init_mtx); return duration < 500 ? 0 : -1; } @@ -226,7 +224,7 @@ int voice_recorder_stop(int* out_duration_ms) { struct audio_compressor* replacement = audio_compressor_clone_config(g_rec->compressor); if (!replacement) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "voice stop: replacement compressor allocation failed"); - u_free(req); u_free(post); voice_cleanup_locked(g_rec); + u_free(req); voice_cleanup_locked(g_rec); pthread_mutex_unlock(&g_rec->mtx); pthread_mutex_unlock(&g_init_mtx); return -1; } req->compressor = g_rec->compressor; g_rec->compressor = replacement; @@ -237,8 +235,9 @@ int voice_recorder_stop(int* out_duration_ms) { voice_cleanup_locked(g_rec); pthread_mutex_unlock(&g_rec->mtx); pthread_mutex_unlock(&g_init_mtx); DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "voice stop: detached target=%s pm=%d duration=%d", req->target, req->is_dm, duration); - post->callback = attachment_send_trampoline; post->arg = req; - uasync_post_reserved(ua, post); + if (instance_lite_post(attachment_send_trampoline, req, &req->inst, attachment_send_discard)) { + DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "voice stop: worker rejected detached recording"); attachment_send_discard(req); return -1; + } return 0; }