• src/sbbs3/ctrl/MainFormUnit.cpp

    From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Mon Jan 12 22:51:03 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/f65fd89a106023a5aa7570ce
    Modified Files:
    src/sbbs3/ctrl/MainFormUnit.cpp
    Log Message:
    Resolve crashes during graceful server termination(s)

    These crashes have been happening seemingly forever, but only noticed (by me) when running in a debugger, otherwise Windows seems to suppress any exception message/popup since the process terminates anyway.

    The problem appears to be that we were setting app controls (e.g. start/stop button states) in the startup->set_state callbacks and it was possible through race conditions that the application (or at least the forms) were actually destroyed already at the time those callbacks are called (to a report server state of STOPPED as one of the last things each server thread does).

    The solution was to store the value of the reported server states in (global) variables and asynchronously (at "appy time") update the relevant controls based on the server state(s). Since the LogTimer runs more frequently (2Hz) than UpTimer (1Hz) and isn't stopped (early) during process termination,
    that was the place best-suited to do these control updates.

    In this process, I also made the app controls make more sense (e.g. the
    "Start" button is disabled during server initialization) and the "Abort" dialing while waiting for graceful server termination(s) is much improved
    (e.g. lists all the servers still running), but now it does not popup for 60 seconds after termination requested (rather than 30 seconds as before) - as
    if the user presses "Yes", this initiates an *ungraceful* exit of the program which could result in crashes (though Microsoft seems to suppress the user notification of these).

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Fri Feb 6 03:20:31 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/1856c762225ee58c86995ca9
    Modified Files:
    src/sbbs3/ctrl/MainFormUnit.cpp
    Log Message:
    Don't update Clients form directly from startup->client_on() callback

    This apppears to finally at long last resolve the "Index out of range" error
    - it's simply not safe to update GUI controls from other threads, so we're doing the update from the LogTimerTick (using a linked-list/queue of changes).

    The log timer ticks at 2Hz (we could increase that), so the Clients list isn't quite as "real time" as before, but it's plenty fast and smooth for my liking.

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Wed Mar 11 02:35:20 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/b628ad930c2f4ed85b559c6c
    Modified Files:
    src/sbbs3/ctrl/MainFormUnit.cpp
    Log Message:
    Restore Form "View states" - don't display always restore all forms as visible

    We've been saving the various form "Visible" states to the Registry forever, but we never restored those states upon startup. e.g. if you didn't want the "Clients" form to be viewable, for example, too bad, it'd also default to shown /visible on startup. That's now fixed: if you turn off the visibilty of any form (the servers, clients, nodes), they'll still off/invisible when you rerun sbbsctrl.

    Also removed some old C++Builder 5 work-around that was forcing the tabsheet's active page to a potentially blank/empty page.

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Wed Apr 22 22:31:11 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/2bceb328e37f8cda3e2affa2
    Modified Files:
    src/sbbs3/ctrl/MainFormUnit.cpp
    Log Message:
    When NT Services are in use, the ServiceStatusTimerTick() controls the status

    start/stop button states, status caption

    Fixes toggling between local server status ("Down") and NT service status
    (e.g. "Running NT Service") as reported by Haxor. Not functional impact, just cosmetic.

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Sat May 23 21:25:45 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/9a207243c5dba9458d1ed0a3
    Modified Files:
    src/sbbs3/ctrl/MainFormUnit.cpp
    Log Message:
    sbbsctrl: don't drop shutdown-summary log lines from disk logs

    The four per-server log handlers (bbs/mail/ftp/web_log_msg) gated disk
    writes on `XxxLogFile && XxxStop->Enabled`, but the latter half closed
    the window too early during a graceful shutdown -- the final
    `#### XxxX Server thread terminated (NN clients served, ...)` summary
    line was logged to the GUI but never persisted to disk, hiding useful operational data (e.g. rate-limit / IP-filter denial counts) from
    post-hoc analysis.

    The `Stop->Enabled` half of the gate is original 2000-era code
    (7e3e47141, "Initial check-in: v3.00c") and worked in practice for 25+
    years by accident: the old `xxx_set_state` switch only handled
    SERVER_STOPPED and SERVER_READY explicitly, so transitional states
    fell through and left `Stop->Enabled` at its previous (true) value
    through the entire shutdown sequence -- only flipping false on the
    final SERVER_STOPPED callback that fires *after* the summary line is
    emitted. The gate happened to be open at exactly the right moment.

    f65fd89a1 ("Resolve crashes during graceful server termination(s)")
    moved control updates out of the background-thread state callbacks
    onto the 2 Hz LogTimer and rewrote the mapping as a strict flat
    assignment:

    MainForm->FtpStop->Enabled = (state == SERVER_READY);

    That tightened `Stop->Enabled` from "best-effort proxy for
    is-server-running" to literally `state == SERVER_READY`. As soon as
    shutdown begins, state leaves SERVER_READY, the next LogTimer tick
    flips the flag to false, and disk logging stops -- well before the
    summary line is emitted. The fix didn't introduce the gate; it just
    removed the slack that was masking it.

    d0252720e ("sbbsctrl: Add 'Log to Disk' option for Terminal and Web
    servers", resolves #1108) then added disk logging to Telnet and Web
    and copied the Mail/FTP gate pattern verbatim, so those two arrived
    broken.

    Drop the `XxxStop->Enabled` half of the gate in all four handlers;
    the user's "Log to Disk" preference alone is the right condition.

    Resolves #1146

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

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Sat May 23 21:46:34 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/1082de20dca523f276c780ba
    Modified Files:
    src/sbbs3/ctrl/MainFormUnit.cpp
    Log Message:
    sbbsctrl: fflush per-server disk-log streams after each write

    Follow-up to 9a207243c (resolved #1146): with the Stop->Enabled gate
    removed, the shutdown-summary line now reaches the disk-log fwrite() in
    each of the four xxx_log_msg() handlers -- but rob noticed that the
    line still didn't *appear* in the file until sbbsctrl was quit. Cause: _fsopen() returns a fully-buffered stream, and the handlers never flush; written data sits in the CRT buffer until the close sentinel (msg==NULL)
    calls fclose() at sbbsctrl shutdown, or until the next date rollover
    recreates the file.

    Add a plain fflush(LogStream) after each fwrite(). On Windows this is essentially free -- fflush copies the CRT buffer to the OS page cache
    (no FlushFileBuffers, no disk sync), and the OS handles physical
    writeback on its own schedule -- so per-line flushing is fine and
    avoids the "lines stranded indefinitely after the last write of a
    quiet period" failure mode of any timer/threshold-based scheme.

    Same provenance as the previous fix: the missing-fflush has been in
    the Mail/FTP handlers since the initial v3.00c import in 2000
    (7e3e47141), and was propagated to the new Telnet/Web handlers in
    d0252720e (resolves #1108).

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

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