Skip to content

Run-state follow-ups: startup-event fix, stoppable Watcher, C API run state, AgentApp tests#11

Merged
pbosetti merged 5 commits into
v2from
code_coverage
Jul 12, 2026
Merged

Run-state follow-ups: startup-event fix, stoppable Watcher, C API run state, AgentApp tests#11
pbosetti merged 5 commits into
v2from
code_coverage

Conversation

@pbosetti

Copy link
Copy Markdown
Owner

Follow-ups to the Mads::Runtime refactor merged in #10, completing the run-state story for v2.4.0. Five commits:

  • a43a564 fix: startup-event use-after-free. register_event(event_type::startup) published from a detached thread holding a raw this through a 500 ms delay; any agent destroyed within that window (e.g. a short-lived events-enabled AgentApp) was a use-after-free. The thread is now owned by the agent, wakes early on shutdown/disconnect via a condition variable, and is joined while the sockets are still open. Publisher sends are also serialized with a mutex, closing a pre-existing data race between the delayed event thread and the owner thread.
  • 3f86a3b feat: stoppable Watcher. Watcher::watch() can now be ended with stop() or by a process-wide stop request; all platform waits are bounded (~1 s). The broker joins its settings-watcher thread on shutdown in both daemon and interactive modes instead of leaking it.
  • b585fbc feat: run state in the C API and Python. New agent_stop(), agent_running(), mads_stop_process(), mads_process_running() (backed by a new public Agent::running() accessor — the exact condition loop() checks), plus Agent.stop(), the Agent.running property, and module-level stop_process()/process_running() in the ctypes wrapper. C and Python agents can now drive and end receive loops cleanly instead of relying on signals.
  • 340ba90 test: AgentApp coverage. 11 new test cases for AgentAppT (CLI plumbing, --help/--version/--save-settings against an in-process fake broker, crypto option propagation, events-enabled connect/disconnect over loopback); the usage example now shows stopping the loop via the agent's Runtime and points at RUNTIME.md; src/agent_app.hpp leaves the coverage ignore lists at 78% covered.
  • ad2677f docs: CHANGES.md entries under the unreleased v2.4.0 and new RUNTIME.md sections for C/Python agents and the Watcher.

Verification

  • Full suite: 215/215 tests passing (~16 s, no broker/DB/network).
  • Coverage: 83.6% lines on the curated denominator (Codecov's blocking 80% project gate passes; the denominator grew by the 262-line agent_app.hpp).
  • The Coverage workflow on head ad2677f is green end to end, including the Codecov upload.
  • Full apps build (MADS_BUILD_APPS=ON, MongoDB, tools) compiles cleanly — 272 targets including the modified broker and plugin loaders.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QM4yHBNnLAp1fyoeSLc4C1


Generated by Claude Code

pbosetti added 5 commits July 12, 2026 06:23
…er sends

register_event(event_type::startup) detached a thread capturing raw
'this' that slept 500 ms before publishing: any agent destroyed within
that window was a use-after-free (AgentApp::connect() takes this path
whenever events are enabled). The thread is now a member, waits on a
condition variable with the per-agent stop request as predicate, and is
woken and joined by shutdown()/disconnect() while the sockets are still
open.

Since that thread publishes concurrently with the owner thread and ZMQ
sockets are not thread-safe, sends on the publisher socket are now
serialized with a mutex (a pre-existing race for any agent publishing
within 500 ms of connecting).
Watcher::watch() looped on while(true) with no way to end it: the
broker leaked its settings watcher in a detached thread and tests had to
intentionally leak Watchers. watch() now runs while neither stop() nor a
process-wide stop (Mads::Runtime::stop_process(), e.g. SIGINT) has been
requested, and all platform waits are bounded (~1 s) so a stop is noticed
promptly. The broker now owns its watcher thread and joins it during
shutdown in both daemon and interactive modes.
New C functions completing the Mads::Runtime story for C and Python
agents: agent_stop() stops one agent's loops, agent_running() reports
whether an agent should keep going (typical loop: while(agent_running(a))
receive), mads_stop_process()/mads_process_running() handle the
process-wide level. Backed by a new public Agent::running() accessor
(the condition loop() itself checks). The Python ctypes wrapper gains
Agent.stop(), the Agent.running property, and module-level
stop_process()/process_running().
New unit suite for AgentAppT: CLI option plumbing (settings/name/id/
queue-size/crypto), the standard early-exit options (--help, --version,
--save-settings against an in-process fake broker and the local-settings
error path), apply_receive_timeout/apply_queue_size, set_agent_name,
restart_if_requested's no-restart path, and the events-enabled
connect/disconnect flow over loopback. The usage example now shows how
to stop the loop via the agent's Runtime and points at RUNTIME.md.
src/agent_app.hpp leaves the gcovr/codecov ignore lists: 78% covered,
with the remainder being std::exit/execvp paths and the UDP discovery
branch. Project coverage: 83.6% (215 tests).
@pbosetti pbosetti merged commit 52648b1 into v2 Jul 12, 2026
4 of 5 checks passed
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.35897% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 53.1%. Comparing base (8a10d71) to head (ad2677f).
⚠️ Report is 6 commits behind head on v2.

Files with missing lines Patch % Lines
src/agent.cpp 50.0% 0 Missing and 10 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##              v2     #11     +/-   ##
=======================================
+ Coverage   52.5%   53.1%   +0.6%     
=======================================
  Files         10      11      +1     
  Lines       1830    2081    +251     
  Branches     847     943     +96     
=======================================
+ Hits         961    1107    +146     
- Misses       324     342     +18     
- Partials     545     632     +87     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant