• src/sbbs3/main.cpp sbbs.h str.cpp

    From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Sat Jun 6 02:23:46 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/9cf170c0246a40f6d502d8b1
    Modified Files:
    src/sbbs3/main.cpp sbbs.h str.cpp
    Log Message:
    Terminal server: fully transmit pre-disconnect message before close (#1157)

    Messages shown to a client immediately before disconnecting (nonodes.txt
    when all nodes are full or node init fails, and badip.msg/badhost.msg for blocked clients) were intermittently not seen by the caller.

    Root cause: these paths printed the file then called flush_output(), which waits on outbuf.empty_event. That event fires when output_thread moves the ring-buffer contents into its *linear* buffer (RingBufRead), not when those bytes are actually sent over the socket. flush_output() therefore returned
    in the gap between ring->linear hand-off and the sendsocket(), the caller closed the socket, and output_thread's send then failed on the closed FD ("!ERROR ... sending on socket"). The result was a thread-scheduling race, matching the reporter's intermittent, protocol-independent symptom.

    Add sbbs_t::WaitForOutbufDrained(timeout): wait for the ring buffer to
    empty AND for output_thread's linear buffer to be transmitted, tracked via
    a new output_thread_busy atomic (set before the ring->linear read so the empty_event hand-off can't be mistaken for "everything sent", cleared once
    the linear buffer is fully sent). Use it in place of flush_output() at the
    two nonodes.txt disconnect sites (main.cpp) and in trashcan_msg() (str.cpp).

    flush_output() is retained for outcom()'s transmit-backpressure retry loop, where "wait for ring-buffer space" (with its online short-circuit) is the correct semantics.

    The nonodes drop-before-close pattern is from ff1aae498 (same-3-jazz); trashcan_msg()'s flush_output(500) is from 424dfe107 (cold-36-task); the underlying empty_event-means-ring-drained-not-sent gap is inherent to the two-stage output_thread design.

    Reported by xbit with detailed cross-client testing.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net