From b9d77e63ddd998bcf58799eeed91655cddd117e2 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Thu, 27 Aug 2026 16:34:32 +0200 Subject: [PATCH] Writer: a START that fails for a reason of someone else's type still answers ProcessStartMessage caught JFJochException only, the same narrow catch ProcessPreflight had. Everything that makes a failed START reportable sits inside that handler - the Error state, err, and the fatal ACK - so an exception of any other type skipped all three and left the broker blocked on an ACK that never came, with the detector about to be armed. It reads that silence as a dead writer and reports a timeout instead of the reason, and the writer is left out of the Error state it should have entered. Not every thrower on this path is ours: std::filesystem::exists throws filesystem_error when the output path cannot be walked at all (a directory component with no search permission, a symlink loop), and SetupFinalizedFileSocket throws ZeroMQ's own type. Now catches std::exception. Logger::ErrorException already takes std::exception, so the handler body is unchanged. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_016L1qig74oYQzfUJJZbbxFh --- writer/StreamWriter.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/writer/StreamWriter.cpp b/writer/StreamWriter.cpp index 806a8662..8a079e0f 100644 --- a/writer/StreamWriter.cpp +++ b/writer/StreamWriter.cpp @@ -78,7 +78,13 @@ void StreamWriter::ProcessStartMessage() { image_puller_output.cbor->start_message->number_of_images); state = StreamWriterState::Started; NotifyTcpAck(TCPFrameType::START, true, false, TCPAckCode::None); - } catch (const JFJochException &e) { + } catch (const std::exception &e) { + // std::exception, not JFJochException: everything below this point - the error state, err, + // and above all the fatal ACK - is skipped if the exception escapes, and the broker is + // blocked on that ACK with the detector about to be armed. It would read the silence as a + // dead writer and report a timeout in place of the reason. Not every thrower here is ours: + // std::filesystem::exists throws filesystem_error when the output path cannot be walked, + // and SetupFinalizedFileSocket throws ZeroMQ's own type. logger.ErrorException(e); logger.Error("Error writing start message - switching to error state"); state = StreamWriterState::Error;