Skip to content

Commit 31ccbea

Browse files
committed
FEATURE-ci-darwin-header-deadline: Conclude bounded diagnostic stage
Restore every temporary source, test and workflow change to exact c0 bytes and remove the trace header. Record the unmodified root-context native prefix pass as intermittency, without a cause, independence, repair or full gate claim. Preserve original failures in a separate pending investigation card; current diagnostic stage awaits Groundwork validation/finalization. Verification: 1283 base source/test/.github files match bytes and modes; staged delta from base is documentation only; git diff --check passes. No C++ or broad suites repeated.
1 parent 60caf5d commit 31ccbea

12 files changed

Lines changed: 180 additions & 669 deletions

‎.github/workflows/v3-package-validation.yml‎

Lines changed: 0 additions & 222 deletions
Large diffs are not rendered by default.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# FEATURE-ci-darwin-header-deadline-followup: Unresolved Darwin external deadline failure
2+
3+
Status: Pending — cause unknown; further diagnostic decision deferred until safe,
4+
confirmed independent CI fixes are finished. No new investigation is authorized
5+
by this record alone.
6+
7+
Predecessor: [bounded native diagnostic stage](FEATURE-ci-darwin-header-deadline.md).
8+
Evidence source: `v3` c0 `c0cfdabc8040273d60c610269a93d1c687ed8517` and prior
9+
f91 native archive failure. Choose the eventual implementation base when scheduled.
10+
11+
## Preserved defect and requirements
12+
13+
Installed shared TLS-off Darwin `external_http1_e2e`, case
14+
`published_header_deadline_drives_empty_dispatch`, failed in f91 archive run
15+
`39962644789` / job `120444991323` / artifact `12506406058`, and c0 archive run
16+
`39969790346` / job `120469466623` / artifact `12509855171`. On c0 the case took
17+
10,006.1 ms: original assertion 217 (`receive_close`) and 221 (`!failed`) failed;
18+
219 (`empty_dispatches > 0`) passed. Other three cases and native HTTP1 passed.
19+
Preserve the original 300 ms header deadline, 10 s host failure deadline and
20+
assertions. Original failed gates remain open/incomplete; the defect is not fixed.
21+
22+
## Completed bounded checks and limits
23+
24+
The predecessor's approved controls are finished. Live and deferred trace overlays
25+
on the exact selected archive passed the four external cases, first in runner
26+
context, then with corrected EUID 0 and original signal defaults. Their healthy
27+
~303 ms timer/continuation/enforcement/native-close sequences prove no cause;
28+
instrumentation can change scheduling. No decisive forced-interleaving regression
29+
or broken wake/lease-retirement invariant was established.
30+
31+
Final run `39990090304` / macOS job `120539322802` used unchanged selected c0
32+
archive/core/test/helpers, original package_lane setup/prelude and first two
33+
TLS-off shared suites, direct original Popen and actual EUID 0. Native HTTP1
34+
60 tests / 708 checks and external four / 52 passed; header 303.348 ms.
35+
Original receipt checks preceded the partial stop. This establishes intermittency,
36+
not cause, fix, independence or whole-matrix passage. Sampling was not triggered;
37+
actual native sampler execution remains untested. Local real-process controller
38+
checks do not substitute for native failure evidence.
39+
40+
Same-c0 checkout package job `120468733495` also passed TLS-off before a separate
41+
TLS-on CA failure. Archive versus checkout/setup was an observed contrast, not
42+
an explanation. Root execution correction did not establish a deadline cause.
43+
All temporary source/test/workflow diagnostics were removed in the predecessor;
44+
its original source/test/workflow tree equals c0 exactly.
45+
46+
## Pending work when scheduled
47+
48+
- [ ] After independent confirmed Windows staging, TLS CA fixture and FreeBSD
49+
selected-make fixes are finished, make the next explicit diagnostic decision
50+
from retained evidence. No unchanged retry or additional probe is implied.
51+
- [ ] If further investigation is authorized, define one bounded question and
52+
stopping condition; preserve source/runtime context and original failures.
53+
- [ ] Establish a concrete cause and observe a meaningful failing actual-code
54+
regression before any narrow behavior repair; preserve budgets/assertions.
55+
- [ ] Validate a proven repair with relevant local checks and assigned native CI;
56+
remove any newly authorized diagnostics before finalization.
57+
58+
The closed prior Linux parity/publication-wait uncertainty is not reopened.
59+
No dependency/policy change, broad baseline, assertion relaxation, timeout
60+
increase or unrelated repair is authorized here.
61+
62+
Primary evidence: `.debug/ci-darwin-native-69af4dxe/journal.md`, original c0/f91
63+
logs/receipts, `original-prefix-summary.json`, `original-prefix-external.log`,
64+
and retained original-prefix diagnostic/sampling/suites/commands receipts.
65+
Final control source artifact `12508482722` (run `39969790346`, attempt 1), tar
66+
SHA-256 `43124552f20bd00fceddc714856d605ca9caf017a849a991c34f16f437fcab83`.
67+
The predecessor card records complete archive and evidence ZIP bindings.

‎specs/tasks/FEATURE-ci-darwin-header-deadline.md‎

Lines changed: 112 additions & 253 deletions
Large diffs are not rendered by default.

‎src/detail/connection_engine.cpp‎

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
#include <httpserver/detail/diagnostics_access.hpp>
4242
#include <httpserver/http/outcome.hpp>
4343

44-
#include <httpserver/detail/deadline_trace.hpp>
45-
4644
namespace httpserver {
4745

4846
namespace detail {
@@ -717,9 +715,6 @@ bool connection_engine::watchdog_due(
717715
std::chrono::steady_clock::time_point deadline) {
718716
std::lock_guard<std::mutex> lock(mu_);
719717
const watchdog_plan plan = plan_watchdog_locked();
720-
V3_DEADLINE_TRACE("due conn=%llu planned_ns=%lld current_ns=%lld now_ns=%lld exit=%d defer=%d equal=%d\n",
721-
static_cast<deadline_trace_id>(id_), deadline_trace_ns(deadline), deadline_trace_ns(plan.deadline),
722-
deadline_trace_ns(std::chrono::steady_clock::now()), plan.exit, plan.defer, plan.deadline == deadline);
723718
return !plan.exit && !plan.defer && plan.deadline == deadline
724719
&& std::chrono::steady_clock::now() >= deadline;
725720
}
@@ -745,8 +740,6 @@ void connection_engine::note_transport_activity(bool written) {
745740
}
746741

747742
void connection_engine::enforce_timeout(std::chrono::steady_clock::time_point deadline) noexcept {
748-
V3_DEADLINE_TRACE("enforce conn=%llu deadline_ns=%lld now_ns=%lld\n",
749-
static_cast<deadline_trace_id>(id_), deadline_trace_ns(deadline), deadline_trace_ns(std::chrono::steady_clock::now()));
750743
bool global_expiry = false, close_expiry = false;
751744
{
752745
std::lock_guard<std::mutex> lock(mu_);
@@ -783,19 +776,13 @@ task<void> connection_engine::watchdog_loop(
783776
std::lock_guard<std::mutex> lock(self->mu_);
784777
plan = self->plan_watchdog_locked();
785778
}
786-
V3_DEADLINE_TRACE("plan conn=%llu deadline_ns=%lld now_ns=%lld exit=%d defer=%d\n",
787-
static_cast<deadline_trace_id>(self->id_), deadline_trace_ns(plan.deadline),
788-
deadline_trace_ns(std::chrono::steady_clock::now()), plan.exit, plan.defer);
789779
if (plan.exit) co_return;
790780
const auto deadline = plan.defer
791781
? std::chrono::steady_clock::now() + k_watchdog_tick
792782
: plan.deadline;
793783
timer_operation op(self->owner_, self->id_, deadline);
794784
if (!self->arm_watchdog(op, plan)) continue;
795785
const io_result r = co_await std::move(op);
796-
V3_DEADLINE_TRACE("watchdog_resume conn=%llu seq=%llu result=%d now_ns=%lld\n",
797-
static_cast<deadline_trace_id>(self->id_), static_cast<deadline_trace_id>(op.sequence()),
798-
static_cast<int>(r.code), deadline_trace_ns(std::chrono::steady_clock::now()));
799786
{
800787
std::lock_guard<std::mutex> lock(self->mu_);
801788
self->pending_timer_.reset();

‎src/detail/connection_engine_websocket.cpp‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
#include <utility>
2626
#include <httpserver/detail/connection_engine.hpp>
2727
#include <httpserver/detail/http1_websocket_handshake.hpp>
28-
29-
#include <httpserver/detail/deadline_trace.hpp>
3028
namespace httpserver::detail {
3129
namespace {
3230
bool retire_completed_front(http1_response_outbox& outbox) {
@@ -238,15 +236,9 @@ bool connection_engine::transport_output_pending_locked() const {
238236
bool connection_engine::arm_watchdog(timer_operation& timer, const watchdog_plan& plan) {
239237
std::lock_guard lock(mu_);
240238
const auto current = plan_watchdog_locked();
241-
V3_DEADLINE_TRACE("arm_check conn=%llu planned_ns=%lld current_ns=%lld exit=%d defer=%d current_defer=%d\n",
242-
static_cast<deadline_trace_id>(id_), deadline_trace_ns(plan.deadline), deadline_trace_ns(current.deadline),
243-
current.exit, plan.defer, current.defer);
244239
if (current.exit) return false;
245240
if (current.defer != plan.defer || current.deadline != plan.deadline) return false;
246241
pending_timer_ = timer.state();
247-
V3_DEADLINE_TRACE("arm conn=%llu token=%p deadline_ns=%lld now_ns=%lld header_ms=%lld\n",
248-
static_cast<deadline_trace_id>(id_), static_cast<void*>(timer.state().get()), deadline_trace_ns(timer.deadline()),
249-
deadline_trace_ns(std::chrono::steady_clock::now()), deadline_trace_ms(config_.timeouts.header));
250242
timer.submit(backend_);
251243
return true;
252244
}

‎src/detail/io_external_adapter.cpp‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
#include <utility>
3232
#include <vector>
3333

34-
#include <httpserver/detail/deadline_trace.hpp>
35-
3634
namespace httpserver {
3735
namespace detail {
3836
namespace {
@@ -94,13 +92,10 @@ void io_poll_backend::notify() {
9492
bool failed = false;
9593
{
9694
std::lock_guard<std::mutex> lock(mu_);
97-
V3_DEADLINE_TRACE("notify backend=%p pending=%d failed=%d\n", static_cast<void*>(this), wake_pending_, wake_failed_);
9895
if (wake_failed_ || wake_pending_) return;
9996
if (wake_.signal()) {
100-
V3_DEADLINE_TRACE("signal backend=%p result=1\n", static_cast<void*>(this));
10197
wake_pending_ = true;
10298
} else {
103-
V3_DEADLINE_TRACE("signal backend=%p result=0\n", static_cast<void*>(this));
10499
wake_failed_ = true;
105100
active_ = false;
106101
failed = true;
@@ -112,10 +107,8 @@ void io_poll_backend::notify() {
112107
}
113108

114109
void io_poll_backend::acknowledge_wake() {
115-
V3_DEADLINE_TRACE("acknowledge backend=%p pending=%d failed=%d\n", static_cast<void*>(this), wake_pending_, wake_failed_);
116110
if (!wake_.acknowledge()) wake_failed_ = true;
117111
wake_pending_ = false;
118-
V3_DEADLINE_TRACE("acknowledged backend=%p failed=%d\n", static_cast<void*>(this), wake_failed_);
119112
}
120113

121114
server::interest_snapshot io_poll_backend::interests() const {
@@ -168,7 +161,6 @@ http::outcome io_poll_backend::dispatch(
168161
close();
169162
return status;
170163
}
171-
V3_DEADLINE_TRACE("dispatch backend=%p events=%zu now_ns=%lld\n", static_cast<void*>(this), events.size(), deadline_trace_ns(now));
172164
for (const auto& event : events) dispatch_event(event);
173165
expire_due_timers(now);
174166
return ready();

‎src/detail/io_operation.cpp‎

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -27,45 +27,10 @@
2727

2828
#include "httpserver/detail/io_operation.hpp"
2929

30-
#if defined(HTTPSERVER_DIAG_HEADER_DEADLINE)
31-
#include <algorithm>
32-
#include <array>
33-
#endif
3430
#include <exception>
3531
#include <memory>
3632
#include <utility>
3733

38-
#include <httpserver/detail/deadline_trace.hpp>
39-
40-
#if defined(HTTPSERVER_DIAG_HEADER_DEADLINE)
41-
namespace httpserver::detail {
42-
namespace {
43-
constinit std::array<deadline_trace_record, 2048> deadline_records{};
44-
constinit std::atomic<std::size_t> deadline_record_count{0};
45-
} // namespace
46-
47-
deadline_trace_record* deadline_trace_reserve(long long monotonic_ns) noexcept { // NOLINT(runtime/int)
48-
const auto index = deadline_record_count.fetch_add(1, std::memory_order_relaxed);
49-
if (index >= deadline_records.size()) return nullptr;
50-
auto& record = deadline_records[index];
51-
record.monotonic_ns = monotonic_ns;
52-
return &record;
53-
}
54-
55-
void deadline_trace_flush() noexcept {
56-
const int saved_errno = errno;
57-
const auto count = std::min(deadline_record_count.load(std::memory_order_relaxed), deadline_records.size());
58-
for (std::size_t index = 0; index < count; ++index) {
59-
const auto& record = deadline_records[index];
60-
if (!record.ready.load(std::memory_order_acquire)) continue;
61-
std::fprintf(stderr, "V3_DEADLINE event_ns=%lld ", record.monotonic_ns); // NOLINT(build/include_what_you_use)
62-
record.write(record);
63-
}
64-
errno = saved_errno;
65-
}
66-
} // namespace httpserver::detail
67-
#endif
68-
6934
namespace httpserver {
7035
namespace detail {
7136

@@ -144,13 +109,6 @@ void op_state::apply(io_result result) {
144109
witness = std::move(witness_);
145110
resume_ex = std::exchange(resume_ex_, nullptr);
146111
}
147-
#if defined(HTTPSERVER_DIAG_HEADER_DEADLINE)
148-
if (kind_ == io_op_kind::timer) {
149-
V3_DEADLINE_TRACE("apply conn=%llu token=%p seq=%llu result=%d frame=%d executor=%d now_ns=%lld\n",
150-
static_cast<deadline_trace_id>(connection_), static_cast<void*>(this), static_cast<deadline_trace_id>(sequence()),
151-
static_cast<int>(result.code), static_cast<bool>(frame), resume_ex != nullptr, deadline_trace_ns(std::chrono::steady_clock::now()));
152-
}
153-
#endif
154112
if (frame) {
155113
resume_guarded(resume_ex, witness, frame);
156114
}

‎src/detail/io_poll_backend.cpp‎

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@
4343
#include "httpserver/detail/io_connection_owner.hpp"
4444
#include "httpserver/detail/io_timer_sweep.hpp"
4545

46-
#include <httpserver/detail/deadline_trace.hpp>
47-
4846
namespace httpserver {
4947
namespace detail {
5048
namespace {
@@ -124,13 +122,6 @@ void io_poll_backend::submit(op_state& op) {
124122
registered = true;
125123
}
126124
}
127-
#if defined(HTTPSERVER_DIAG_HEADER_DEADLINE)
128-
if (op.kind() == io_op_kind::timer) {
129-
V3_DEADLINE_TRACE("submit conn=%llu token=%p seq=%llu registered=%d rejected=%d admission=%d deadline_ns=%lld\n",
130-
static_cast<deadline_trace_id>(op.connection()), static_cast<void*>(&op), static_cast<deadline_trace_id>(op.sequence()),
131-
registered, rejected, static_cast<int>(admission), deadline_trace_ns(std::get<timer_payload>(op.payload()).deadline));
132-
}
133-
#endif
134125
if (rejected) {
135126
finish_now(state, closed_result());
136127
return;
@@ -286,7 +277,6 @@ pollsys::native_socket_t io_poll_backend::native_handle(
286277
}
287278

288279
void io_poll_backend::release_connection(std::uint64_t id) {
289-
V3_DEADLINE_TRACE("release conn=%llu now_ns=%lld\n", static_cast<deadline_trace_id>(id), deadline_trace_ns(std::chrono::steady_clock::now()));
290280
hangup_connection(id);
291281
}
292282

@@ -326,10 +316,6 @@ void io_poll_backend::hangup_connection(std::uint64_t id,
326316
if (expected && (cit == connections_.end()
327317
|| cit->second.lifetime != expected)) return;
328318
if (cit != connections_.end() && cit->second.lifetime) {
329-
V3_DEADLINE_TRACE("retire conn=%llu socket=%llu lease=%p generation=%llu leases=%ld\n",
330-
static_cast<deadline_trace_id>(id), static_cast<deadline_trace_id>(cit->second.socket),
331-
static_cast<void*>(cit->second.lifetime.get()),
332-
static_cast<deadline_trace_id>(cit->second.lifetime->generation), cit->second.lifetime.use_count());
333319
cit->second.dead = true;
334320
cit->second.lifetime->retired.store(true, std::memory_order_release);
335321
cit->second.lifetime.reset();
@@ -369,9 +355,6 @@ std::uint64_t io_poll_backend::register_accepted_socket(
369355
connection_record record;
370356
record.socket = socket;
371357
record.lifetime = make_lifetime_locked(socket);
372-
V3_DEADLINE_TRACE("accepted conn=%llu socket=%llu lease=%p generation=%llu\n",
373-
static_cast<deadline_trace_id>(id), static_cast<deadline_trace_id>(socket),
374-
static_cast<void*>(record.lifetime.get()), static_cast<deadline_trace_id>(record.lifetime->generation));
375358
connections_[id] = std::move(record);
376359
return id;
377360
}

‎src/detail/io_poll_sys.cpp‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
#include <httpserver/detail/io_poll_sys.hpp>
33
#include <string>
44

5-
#include <httpserver/detail/deadline_trace.hpp>
6-
75
namespace httpserver::detail::pollsys {
86

97
int poll_call(poll_slot* slots, std::size_t count, int timeout_ms) {
@@ -39,10 +37,7 @@ bool close_socket(native_socket_t& socket) {
3937
#if defined(_WIN32)
4038
return ::closesocket(closing) == 0;
4139
#else
42-
const int result = ::close(closing);
43-
V3_DEADLINE_TRACE("native_close socket=%llu result=%d errno=%d now_ns=%lld\n",
44-
static_cast<deadline_trace_id>(closing), result, result == 0 ? 0 : errno, deadline_trace_ns(std::chrono::steady_clock::now()));
45-
return result == 0;
40+
return ::close(closing) == 0;
4641
#endif
4742
}
4843

‎src/detail/io_timer_sweep.cpp‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#include <httpserver/detail/io_connection_owner.hpp>
88
#include <httpserver/detail/io_timer_sweep.hpp>
99

10-
#include <httpserver/detail/deadline_trace.hpp>
11-
1210
namespace httpserver::detail {
1311

1412
std::size_t sweep_due_timers(std::unordered_map<op_state*, std::shared_ptr<op_state>>& pending, std::mutex& mu, std::chrono::steady_clock::time_point now) {
@@ -33,9 +31,6 @@ std::size_t sweep_due_timers(std::unordered_map<op_state*, std::shared_ptr<op_st
3331
});
3432
std::size_t expired = 0;
3533
for (const auto& entry : due) {
36-
V3_DEADLINE_TRACE("expire conn=%llu token=%p seq=%llu deadline_ns=%lld dispatch_ns=%lld terminal=%d\n",
37-
static_cast<deadline_trace_id>(entry.second->connection()), static_cast<void*>(entry.second.get()),
38-
static_cast<deadline_trace_id>(entry.second->sequence()), deadline_trace_ns(entry.first), deadline_trace_ns(now), entry.second->is_terminal());
3934
if (entry.second->claim_terminal()) {
4035
entry.second->owner()->enqueue(entry.second, io_result{});
4136
++expired;

0 commit comments

Comments
 (0)