You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Major fixes (all 5 addressed):
- Replaced bare catch(...) on unregister_path with catch(invalid_argument) +
catch(exception) with stderr logging — surface unexpected exceptions.
- Added 5 ms inter-request sleep to curl client loop — rate-limits to
~200 req/s under TSan, keeping wall-clock within CI budget.
- Added null check after curl_easy_init() — skip thread gracefully on
resource exhaustion rather than crash.
- Added early return after fork() failure (LT_CHECK(child >= 0)) —
prevents waitpid(-1,...) from reaping unrelated processes.
- TASK-032.md status already Done; assertions already individual (TASK-052).
Minor fixes (cosmetic + docs):
- Added kDynSlots, kIpRange, kExitCodeStopReturned, kExitCodeCurlCompleted
named constants; replaced all hex magic literals (0x7, 0xff, 42, 43).
- Reduced CURLOPT_TIMEOUT_MS in stop-from-handler child to 3000L
(< parent's 5 s window) so timeout ordering is consistent.
- Renamed deadline → child_deadline in stop_from_handler test.
- Replaced std::string(run) with std::string_view(run) for env-var check.
- Added upper bound (v <= 3600) to stress_seconds() (CWE-1284).
- Added comment documenting why register_prefix is intentionally excluded.
- Added @see stop() cross-reference to ~webserver() Doxygen.
- Updated specs/architecture/09-testing.md §9 item 6 to use v2 API names.
- Corrected DR-008.md Verification: exit codes are regression sentinels,
not positive observations; WIFSIGNALED paths are the positive observations.
- Added ~webserver() note to DR-008.md Verification section.
- Added PRD-CON-REQ-001/002 EARS concurrency requirements to product_specs.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: specs/architecture/09-testing.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,6 @@ The architecture itself does not prescribe test frameworks (out of architecture
7
7
3.**Move semantics on `http_response`** (DR-5): sanitizer-clean tests for inline↔inline, inline↔heap, heap↔inline, heap↔heap on both move-construct and move-assign.
8
8
4.**SBO size invariant** (DR-5): `static_assert(sizeof(detail::deferred_body) <= http_response::body_buf_size, ...)` at the end of `detail/body.hpp`. Compile-time guarantee.
9
9
5.**Routing semantics preservation** (DR-7): the v1 routing-test corpus runs against v2.0 unchanged. Any regression is treated as a release-blocker.
10
-
6.**Thread-safety contract** (DR-8): a stress test exercises `register_resource` / `block_ip` from within handlers, verifies no deadlock except for the documented `stop()` case.
10
+
6.**Thread-safety contract** (DR-8): a stress test exercises `register_path` / `unregister_path` / `block_ip`/ `unblock_ip`from within handlers, verifies no deadlock except for the documented `stop()` case. An opt-in negative test (`stop_from_handler_deadlocks_as_documented`, enabled via `HTTPSERVER_RUN_STOP_FROM_HANDLER=1`) confirms the deadlock contract by forking a child that calls `stop()` from inside a handler.
Copy file name to clipboardExpand all lines: specs/architecture/11-decisions/DR-008.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,6 +22,6 @@
22
22
**Verification (TASK-032):**
23
23
-`test/integ/threadsafety_stress.cpp` — stress test binary `threadsafety_stress` runs 16 concurrent curl clients for 60 seconds (override via `HTTPSERVER_STRESS_SECONDS=N`), each request randomly invoking `register_path`, `unregister_path`, `block_ip`, and `unblock_ip` against the running `webserver` from inside a handler thread. A duplicate-registration from a handler throws `std::invalid_argument` rather than causing a data race.
24
24
- CI coverage: the `build-type: tsan` matrix entry in `.github/workflows/verify-build.yml` compiles with `-fsanitize=thread` and runs `make check`, which automatically picks up `threadsafety_stress` as a registered `check_PROGRAMS` entry — no separate workflow wiring is needed.
25
-
- Opt-in negative test `stop_from_handler_deadlocks_as_documented` (enabled via `HTTPSERVER_RUN_STOP_FROM_HANDLER=1`) forks a child process that calls `stop()` from inside a handler. A non-zero child exit (libmicrohttpd self-join abort, exit code 42) or a 5-second parent timeout (exit code 43) both count as positive observation of the documented deadlock contract. These exit codes serve as regression sentinels.
25
+
- Opt-in negative test `stop_from_handler_deadlocks_as_documented` (enabled via `HTTPSERVER_RUN_STOP_FROM_HANDLER=1`) forks a child process that calls `stop()` from inside a handler. Positive observations of the contract are signal-terminated (libmicrohttpd self-join abort, `WIFSIGNALED`) or SIGKILL-from-parent after a 5-second timeout (silent deadlock, also `WIFSIGNALED`). Two sentinel exit codes mark regressions: the unreachable-after-`stop()` line inside the child (`stop()` returned from a handler — regression) and the post-curl line (`stop()` did not block at all — regression). A zero child exit means `stop()` returned cleanly, which is also a regression against DR-008. `~webserver()` carries the same threading constraint as `stop()` but is not separately exercised because destructor invocation from a running handler is inherently process-unsafe; the `stop()` test is considered representative.
Copy file name to clipboardExpand all lines: specs/product_specs.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,6 +36,9 @@
36
36
-**Hot-path performance:** Per-request getters shall not allocate or copy containers; they return `const&` or `string_view`.
37
37
-**Naming:** All public method names shall be snake_case; one canonical verb per concept.
38
38
-**Documentation:** v2.0 ships with a rewritten `README` and an updated examples set. A short `RELEASE_NOTES.md` summarizes the API changes for users porting from v1; it is informational, not a compatibility commitment.
39
+
-**Concurrency (DR-008):**
40
+
-`PRD-CON-REQ-001` When a caller invokes any `webserver` public method from a handler thread (except `stop()` or `~webserver()`), the system shall complete the call without deadlock or data race.
41
+
-`PRD-CON-REQ-002` When a caller invokes `stop()` or `~webserver()` from inside a handler thread, the system shall either deadlock (join waits indefinitely) or abort (libmicrohttpd self-join detection); it shall not return successfully.
0 commit comments