From c069aa7f5f2beeead1a3a8e9f71510f1b64d0725 Mon Sep 17 00:00:00 2001 From: Pascal Date: Sat, 12 Sep 2026 07:38:50 +0200 Subject: [PATCH] server: frame the router child state command as a whole line (#28747) The child writes its state commands on stdout while the logger writes on stderr, and both share a single pipe. The logger emits the trailing color reset after the newline of a debug, warn or error entry, so that escape sequence has no newline of its own and the router reads it glued in front of the next command. The line prefix check then fails and the command is forwarded as a log line instead of being handled, which leaves a finished download stuck in the downloading state. Writing the command with a leading newline closes the pending line so it always starts at a line boundary. --- tools/server/server-models.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/server/server-models.cpp b/tools/server/server-models.cpp index f1783c083..4984f1be6 100644 --- a/tools/server/server-models.cpp +++ b/tools/server/server-models.cpp @@ -1786,7 +1786,10 @@ void server_child::notify_to_router(const std::string & state, const json & payl std::lock_guard lk(mtx_stdout); common_log_pause(common_log_main()); fflush(stdout); - fprintf(stdout, "%s%s\n", CMD_CHILD_TO_ROUTER_STATE, safe_json_to_str(data).c_str()); + // the router matches the command on a line prefix, so the leading newline + // closes whatever the logger left open on the shared pipe, down to the + // trailing color reset that carries no newline of its own + fprintf(stdout, "\n%s%s\n", CMD_CHILD_TO_ROUTER_STATE, safe_json_to_str(data).c_str()); fflush(stdout); common_log_resume(common_log_main()); }