Keep accepted commands bound to their instance while restart readiness closes

This commit is contained in:
evgeny committed 2026-10-29 13:35:41 +01:00
1 parent f15ca995b7
commit da540627fc
3 files changed
+10 -2

No files matched your search

+3 -1
View File
@@ -307,13 +307,15 @@ static int check_worker_requests(const char* directory) {
pthread_mutex_lock(&worker_test_mutex);
while (!worker_entered) pthread_cond_wait(&worker_test_cond, &worker_test_mutex);
pthread_mutex_unlock(&worker_test_mutex);
int retained_payload = 0;
REQUIRE(!instance_lite_post(worker_payload_run, &retained_payload, NULL, worker_payload_discard));
REQUIRE(!instance_lite_restart("[global]\ndb_path=/nonexistent/utun-restart-identity/missing\n"));
REQUIRE(!instance_lite_is_running());
pthread_mutex_lock(&worker_test_mutex);
worker_release = 1; pthread_cond_broadcast(&worker_test_cond);
pthread_mutex_unlock(&worker_test_mutex);
for (int i = 0; i < 1000 && !instance_lite_is_running(); i++) usleep(10000);
REQUIRE(instance_lite_is_running());
REQUIRE(instance_lite_is_running() && __atomic_load_n(&retained_payload, __ATOMIC_ACQUIRE) == 1);
struct worker_query retained = {0}; REQUIRE(!instance_lite_call(worker_read, &retained) && retained.node == query.node);
pthread_mutex_lock(&worker_test_mutex);
worker_entered = 0; worker_release = 0;
@@ -93,6 +93,9 @@ Worker снимает media-привязки, уничтожает instance, с
каждые две секунды ожидания пишет предупреждение, поток не отсоединяет. Повторный stop безопасен.
Restart пересоздаёт instance и uasync. Возврат restart/updateSockets подтверждает принятие копии INI,
ошибка очереди возвращается Kotlin; готовность нового запуска подтверждается SERVICE_STARTED.
Принятие restart сразу закрывает ready для новых frontend/media запросов. Ошибка подготовки возвращает
ready прежнему instance. Ранее принятые команды могут завершиться в прежнем worker до его снятия;
после снятия instance они отменяются, даже если uasync обрабатывает оставшиеся callbacks при teardown.
Fatal signal handlers принадлежат платформе: worker не заменяет их обработчиком с небезопасными locks/JNI/backtrace.
Общие правила освобождения: `../../../doc/service_lifecycle.md`.
@@ -108,6 +108,7 @@ struct frontend_request {
void (*callback)(void*);
void (*discard)(void*);
void* arg;
struct UTUN_INSTANCE* instance; /* Привязка к публикации; pending restart закрывает ready, но ещё не уничтожает instance. */
};
static struct frontend_request* g_frontend_requests; /* Список под g_stop_mutex. */
@@ -117,7 +118,8 @@ static void frontend_request_run(void* arg) {
struct frontend_request** entry = &g_frontend_requests;
while (*entry && *entry != request) entry = &(*entry)->next;
if (*entry) *entry = request->next;
int cancelled = __atomic_load_n(&g_stop, __ATOMIC_ACQUIRE) || !__atomic_load_n(&g_running, __ATOMIC_ACQUIRE);
int cancelled = __atomic_load_n(&g_stop, __ATOMIC_ACQUIRE) ||
__atomic_load_n(&g_inst, __ATOMIC_ACQUIRE) != request->instance;
pthread_mutex_unlock(&g_stop_mutex);
if (!cancelled) request->callback(request->arg);
else if (request->discard) request->discard(request->arg);
@@ -158,6 +160,7 @@ int instance_lite_post(void (*callback)(void*), void* arg, struct UTUN_INSTANCE*
u_free(task); u_free(request); return -1;
}
if (instance_field) *instance_field = inst;
request->instance = inst;
request->next = g_frontend_requests; g_frontend_requests = request;
uasync_post_reserved(ua, task);
pthread_mutex_unlock(&g_stop_mutex);