• src/sbbs3/main.cpp

    From Rob Swindell (on Windows 11)@1:103/705 to Git commit to main/sbbs/master on Sat May 2 18:58:15 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/ff1aae498b3464b1f2fd050a
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    sbbs3 terminal server: drop unsent goodbye output before close_socket

    In the four listener exit paths that queue output via the listener
    pseudo-sbbs (CLIENT BLOCKED for ip.can / host.can, "no nodes
    available", node init failure), call sbbs->rioctl(IOFB) right after flush_output() and before close_socket(). Without this, any
    text/badip.msg / badhost.msg / nonodes.txt residue that didn't make
    it out within the flush timeout sits in the ring buffer; when the
    output thread next wakes it tries to send the leftover on the
    now-closed FD, and the failed send logs a noisy warning (e.g.
    "!ERROR 22 (...)" or "!ERROR 58 (...)" sending on socket).

    This is the same idiom as the existing rioctl(IOFB) at the start of
    the per-connection setup (main.cpp:5795) — purge stale buffer state
    before changing socket lifecycle.

    It does not eliminate the race entirely: data already pulled from
    the ring buffer into the output thread's linear buffer is still sent
    (or attempted), since rioctl operates on the ring buffer only. The
    remaining noise is handled separately by demoting the typical
    post-shutdown send errors (ESHUTDOWN, EINVAL) to LOG_NOTICE.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Windows 11)@1:103/705 to Git commit to main/sbbs/master on Sat May 2 18:58:15 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/8c6da8b2eee4363c1fcb9925
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    sbbs3 terminal server: include socket/protocol/IP in output_thread send-error logs

    Three coordinated changes to output_thread's SOCKET_ERROR handling:

    * Switch all six log lines from "<node-name> ..." (using sbbs->client_name
    like "Terminal Server" / "Node N") to the standard "%04d %s [%s] ..."
    prefix used by every other connection log line in the file. This
    groups send errors with the matching "Connection accepted",
    "!CLIENT BLOCKED", etc. lines for easy correlation. Capture
    client_socket.load() once into a local since the cascade reads it
    six times (it's std::atomic).

    * Populate the listener pseudo-sbbs's client.protocol and client_ipaddr
    per-connection. These were previously only set inside sbbs_t::init()
    for per-node sbbs's (main.cpp:3639), leaving the listener's
    output_thread with empty strings to print.

    * Demote ESHUTDOWN and EINVAL send errors to LOG_NOTICE alongside the
    existing ENOTSOCK / ECONNRESET / ECONNABORTED handlers. Both are
    the typical errors raised when the listener races with close_socket()
    on a blocked client (post-shutdown / mid-close socket state).
    Treating them as expected disconnect noise matches the existing
    pattern. Note: on POSIX, EINVAL from send() can theoretically
    indicate a programming bug rather than a socket-state race, but in
    practice it's the same race as on Windows and the noise reduction
    is worth the small risk of masking.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Tue May 5 15:55:25 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/88889e94e52406ca3ff0b721
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    node_thread: avoid throttle-loop hang on loginAttempts() failure (CID 645970)

    loginAttempts() returns long and is documented to return a negative
    value on failure, but the result was stored in a uint. On -1 the value
    became UINT_MAX, passed the (> 1) check, and the throttle loop would
    run ~4 billion mswait() iterations. Match the signed return type and
    update the matching format specifier and loop counter.
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Wed May 6 19:41:53 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/ded9a017f3b2199433125aad
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    sbbs_t::lputs: guard event-thread log-level check against null startup (CID 543171)

    sbbs_t::lputs() consults startup->event_log_level when is_event_thread
    is set, but the surrounding callers (e.g. sbbs_t::js_create_user_objects) already treat startup as potentially-null. If any caller reaches an errprintf/lprintf path with startup == nullptr while is_event_thread is
    true, the deref would crash. Add the null check that the call sites
    already assume.

    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Wed May 6 19:41:53 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/ae00ca271149cf268b913ae8
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    main: suppress ssh_mutex/sftp_state inter-procedural FPs (CIDs 469167, 487167)

    CID 469167 (output_thread SLEEP): GCESSTR's lprintf runs while
    ssh_mutex is held. Releasing+reacquiring the mutex around the SSH
    error report would race the surrounding error-handling sequence
    (ssh_errors++, online=FALSE) and is the wrong tradeoff for a fast log
    write. Annotate as intentional design.

    CID 487167 (crypt_pop_channel_data LOCK at function end): sftp_state->mtx
    is acquired+released entirely inside sftps_recv;
    crypt_pop_channel_data never holds it across return. Coverity
    propagates a phantom lock state through the helper.

    Note: CID 487173 (sftp_send LOCK leak in src/sbbs3/sftp.cpp) was
    already mitigated in current source — every error path now releases
    ssh_mutex before returning.

    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Wed May 6 22:36:57 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/d6d35429bd173a0284d8fc5a
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    main: cast cryptSetAttribute SSH_CHANNEL_ACTIVE deactivation to void (CID 487166)

    In crypt_pop_channel_data the inner cryptSetAttribute that flips the
    selected channel inactive is best-effort (we're tearing down anyway).
    Make the discarded return explicit.

    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)