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:
+21
-6
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user