ha(H1): исправления по ревью — жизненный цикл сессии, самодостаточный wheel

- C1: единственный владелец stop+destroy — reader-поток; close() только
  выставляет флаг и ждёт; повторный close и close из колбэка безопасны
  (регресс-тесты; TSan на close с мёртвым модулем — 0 гонок)
- M1: wheel собирается с bundled mbedtls (нет внешней soname mbedcrypto);
  попутно исправлена bundled-ветка CMake (-lSTATIC)
- C-API: счётчики потерянных событий/логов, лог-кольцо без union-балласта,
  атомарные fn/ctx лог-синка
- provision: валидация формата облачных ответов; CLI: человеческие ошибки
  (exit 2), --out с правами 0600, console_script pyfglair
- упаковка: MANIFEST.in (sdist с C++-исходниками), очистка stale .so,
  readme в метаданных; find_library без ложных .bak
- тесты: close-сценарии, доставка логов, ошибки CLI/provision, C-API очередь
This commit is contained in:
2026-09-29 11:48:32 +03:00
parent 0292404756
commit b84bd8d555
18 changed files with 356 additions and 56 deletions
+21 -6
View File
@@ -2,6 +2,7 @@
// обязаны совпадать с C++ enum'ами — проверено static_assert'ами.
#include "fgl-aircon/c_api.h"
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstdio>
@@ -110,6 +111,11 @@ struct Ring {
}
return n;
}
uint64_t dropped_count() {
std::lock_guard<std::mutex> lock(mtx);
return dropped;
}
};
constexpr size_t kSessionEventCap = 64;
@@ -118,8 +124,8 @@ constexpr size_t kLogEventCap = 64;
Ring<fgl_log_event_t, kLogEventCap> g_log_ring;
struct LogWrap {
fgl_log_sink_fn fn;
void* ctx;
std::atomic<fgl_log_sink_fn> fn{nullptr};
std::atomic<void*> ctx{nullptr};
};
LogWrap g_log_wrap;
std::once_flag g_log_installed;
@@ -131,8 +137,9 @@ void log_wrap_trampoline(int level, const char* msg, size_t len, void*) {
memcpy(ev.msg, msg, n);
ev.msg[n] = '\0';
g_log_ring.push(ev);
if (g_log_wrap.fn != nullptr) {
g_log_wrap.fn(level, msg, len, g_log_wrap.ctx);
auto fn = g_log_wrap.fn.load(std::memory_order_acquire);
if (fn != nullptr) {
fn(level, msg, len, g_log_wrap.ctx.load(std::memory_order_relaxed));
}
}
@@ -144,8 +151,8 @@ void ensure_log_pipe() {
} // namespace
void fgl_log_set_sink(fgl_log_sink_fn sink, void* ctx) {
g_log_wrap.fn = sink;
g_log_wrap.ctx = ctx;
g_log_wrap.ctx.store(ctx, std::memory_order_relaxed);
g_log_wrap.fn.store(sink, std::memory_order_release);
// Ядро всегда пишет в кольцевой буфер (его читает pyfglair); sink —
// дополнительный прямой колбэк для C/C++ (только малые стеки!).
ensure_log_pipe();
@@ -292,6 +299,14 @@ int fgl_session_wait_events(fgl_session_t* s, fgl_event_t* out,
return s->events->wait(out, max_events, timeout_ms);
}
uint64_t fgl_session_events_dropped(const fgl_session_t* s) {
return (s != nullptr && s->events != nullptr)
? s->events->dropped_count()
: 0;
}
uint64_t fgl_log_events_dropped(void) { return g_log_ring.dropped_count(); }
fgl_state_t fgl_session_state(const fgl_session_t* s) {
return s != nullptr ? static_cast<fgl_state_t>(s->s->state())
: FGL_STATE_IDLE;