Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion src/core/zr_detect.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum {
ZR_DETECT_READ_ACCUM_CAP = 4096u,
ZR_DETECT_QUERY_TIMEOUT_MS = 100u,
ZR_DETECT_TOTAL_TIMEOUT_MS = 500u,
ZR_DETECT_DA1_DRAIN_TIMEOUT_MS = 20u,
ZR_DETECT_DECRQM_SET = 1u,
};

Expand Down Expand Up @@ -756,6 +757,23 @@ static int32_t zr_detect_read_timeout_slice(uint64_t start_ms, uint32_t spent_ms
return remaining;
}

static int32_t zr_detect_remaining_da1_drain_budget(uint32_t spent_ms) {
if (spent_ms >= (uint32_t)ZR_DETECT_DA1_DRAIN_TIMEOUT_MS) {
return 0;
}
return (int32_t)((uint32_t)ZR_DETECT_DA1_DRAIN_TIMEOUT_MS - spent_ms);
}

static int32_t zr_detect_clamp_timeout_budget(int32_t timeout_ms, int32_t budget_ms) {
if (timeout_ms <= 0 || budget_ms <= 0) {
return 0;
}
if (timeout_ms > budget_ms) {
return budget_ms;
}
return timeout_ms;
}

static zr_terminal_id_t zr_detect_fallback_terminal_id(plat_t* plat) {
zr_terminal_id_t id = ZR_TERM_UNKNOWN;
if (plat_guess_terminal_id(plat, &id) != ZR_OK) {
Expand Down Expand Up @@ -847,8 +865,25 @@ zr_result_t zr_detect_probe_terminal(plat_t* plat, const plat_caps_t* baseline_c

uint64_t start_ms = plat_now_ms();
uint32_t timeout_spent_ms = 0u;
/* DA1 acts as a probe sentinel; after it arrives, drain briefly then stop. */
uint8_t da1_responded = 0u;
uint64_t da1_seen_ms = 0u;
uint32_t da1_drain_spent_ms = 0u;
while (true) {
const int32_t timeout_ms = zr_detect_read_timeout_slice(start_ms, timeout_spent_ms);
int32_t timeout_ms = zr_detect_read_timeout_slice(start_ms, timeout_spent_ms);
if (da1_responded != 0u) {
const uint64_t now_ms = plat_now_ms();
uint32_t da1_elapsed_ms = 0u;
if (now_ms > da1_seen_ms) {
const uint64_t delta_ms = now_ms - da1_seen_ms;
da1_elapsed_ms = (delta_ms > UINT32_MAX) ? UINT32_MAX : (uint32_t)delta_ms;
}
if (da1_elapsed_ms > da1_drain_spent_ms) {
da1_drain_spent_ms = da1_elapsed_ms;
}
const int32_t da1_budget_ms = zr_detect_remaining_da1_drain_budget(da1_drain_spent_ms);
timeout_ms = zr_detect_clamp_timeout_budget(timeout_ms, da1_budget_ms);
}
if (timeout_ms <= 0) {
break;
}
Expand All @@ -860,6 +895,9 @@ zr_result_t zr_detect_probe_terminal(plat_t* plat, const plat_caps_t* baseline_c
}
if (n == 0) {
timeout_spent_ms += (uint32_t)timeout_ms;
if (da1_responded != 0u) {
da1_drain_spent_ms += (uint32_t)timeout_ms;
}
continue;
}

Expand All @@ -871,6 +909,15 @@ zr_result_t zr_detect_probe_terminal(plat_t* plat, const plat_caps_t* baseline_c
memcpy(collected + collected_len, chunk, copy_len);
collected_len += copy_len;
}
if (da1_responded == 0u) {
zr_detect_parsed_t partial;
zr_detect_parsed_reset(&partial);
(void)zr_detect_parse_responses(collected, collected_len, &partial);
da1_responded = partial.da1_responded;
if (da1_responded != 0u) {
da1_seen_ms = plat_now_ms();
}
}
if (collected_len == sizeof(collected)) {
break;
}
Expand Down
12 changes: 6 additions & 6 deletions src/platform/posix/zr_plat_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ typedef void (*zr_posix_sa_sigaction_fn)(int, siginfo_t*, void*);
#error "POSIX signal chaining requires lock-free int/pointer atomics."
#endif
static _Atomic int g_posix_prev_handler_kind = ZR_POSIX_HANDLER_KIND_NONE;
static _Atomic(zr_posix_sa_handler_fn) g_posix_prev_sa_handler = NULL;
static _Atomic(zr_posix_sa_sigaction_fn) g_posix_prev_sa_sigaction = NULL;
static _Atomic(zr_posix_sa_handler_fn) g_posix_prev_sa_handler;
static _Atomic(zr_posix_sa_sigaction_fn) g_posix_prev_sa_sigaction;

/*
POSIX testing hook: force SIGWINCH overflow marker path.
Expand Down Expand Up @@ -734,8 +734,8 @@ static void zr_posix_sigwinch_publish_previous(const struct sigaction* prev) {
return;
}

atomic_store_explicit(&g_posix_prev_sa_handler, NULL, memory_order_relaxed);
atomic_store_explicit(&g_posix_prev_sa_sigaction, NULL, memory_order_relaxed);
atomic_store_explicit(&g_posix_prev_sa_handler, (zr_posix_sa_handler_fn)0, memory_order_relaxed);
atomic_store_explicit(&g_posix_prev_sa_sigaction, (zr_posix_sa_sigaction_fn)0, memory_order_relaxed);
atomic_store_explicit(&g_posix_prev_handler_kind, ZR_POSIX_HANDLER_KIND_NONE, memory_order_relaxed);

if ((prev->sa_flags & SA_SIGINFO) != 0) {
Expand All @@ -758,8 +758,8 @@ static void zr_posix_sigwinch_publish_previous(const struct sigaction* prev) {

static void zr_posix_sigwinch_clear_previous(void) {
atomic_store_explicit(&g_posix_prev_handler_kind, ZR_POSIX_HANDLER_KIND_NONE, memory_order_release);
atomic_store_explicit(&g_posix_prev_sa_handler, NULL, memory_order_relaxed);
atomic_store_explicit(&g_posix_prev_sa_sigaction, NULL, memory_order_relaxed);
atomic_store_explicit(&g_posix_prev_sa_handler, (zr_posix_sa_handler_fn)0, memory_order_relaxed);
atomic_store_explicit(&g_posix_prev_sa_sigaction, (zr_posix_sa_sigaction_fn)0, memory_order_relaxed);
}

static void zr_posix_sigwinch_handler(int signo, siginfo_t* info, void* ucontext) {
Expand Down
5 changes: 3 additions & 2 deletions src/util/zr_assert.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <stdatomic.h>
#include <stdlib.h>

static _Atomic(zr_assert_cleanup_hook_t) g_zr_assert_cleanup_hook = NULL;
static _Atomic(zr_assert_cleanup_hook_t) g_zr_assert_cleanup_hook;
static atomic_flag g_zr_assert_fail_guard = ATOMIC_FLAG_INIT;

void zr_assert_set_cleanup_hook(zr_assert_cleanup_hook_t hook) {
Expand All @@ -23,7 +23,8 @@ void zr_assert_clear_cleanup_hook(zr_assert_cleanup_hook_t hook) {
}

zr_assert_cleanup_hook_t expected = hook;
(void)atomic_compare_exchange_strong_explicit(&g_zr_assert_cleanup_hook, &expected, NULL, memory_order_acq_rel,
const zr_assert_cleanup_hook_t no_hook = (zr_assert_cleanup_hook_t)0;
(void)atomic_compare_exchange_strong_explicit(&g_zr_assert_cleanup_hook, &expected, no_hook, memory_order_acq_rel,
memory_order_acquire);
}

Expand Down
20 changes: 20 additions & 0 deletions tests/unit/test_detect_profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,26 @@ ZR_TEST_UNIT(detect_profile_waits_multiple_timeout_slices) {
zr_test_close_mock_platform(plat);
}

ZR_TEST_UNIT(detect_profile_da1_reply_limits_final_drain_wait) {
mock_plat_reset();

plat_t* plat = NULL;
plat_caps_t baseline;
ZR_ASSERT_EQ_U32(zr_test_open_mock_platform(&plat, &baseline), ZR_OK);

static const uint8_t kResponses[] = "\x1b[?1;2c";
ZR_ASSERT_EQ_U32(mock_plat_push_input(kResponses, sizeof(kResponses) - 1u), ZR_OK);

zr_terminal_profile_t profile;
plat_caps_t out_caps;
ZR_ASSERT_EQ_U32(zr_detect_probe_terminal(plat, &baseline, &profile, &out_caps, NULL, 0u, NULL), ZR_OK);

ZR_ASSERT_EQ_U32(profile.da1_responded, 1u);
ZR_ASSERT_EQ_U32(mock_plat_timed_read_call_count(), 2u);

zr_test_close_mock_platform(plat);
}

ZR_TEST_UNIT(detect_profile_returns_non_probe_passthrough) {
mock_plat_reset();

Expand Down
1 change: 1 addition & 0 deletions tests/unit/test_limits.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "platform/zr_platform.h"
#include "unicode/zr_width.h"
#include "util/zr_caps.h"
#include "util/zr_macros.h"

#include <stdio.h>
#include <stdlib.h>
Expand Down
Loading