BBS:      TELESC.NET.BR
Assunto:  sbbsctrl drops shutdown-summary log line from disk log (Stop->Enabled
De:       Rob Swindell
Data:     Sat, 23 May 2026 21:23:22 -0700
-----------------------------------------------------------
https://gitlab.synchro.net/main/sbbs/-/issues/1146#note_9021

## Historical context  why this gate worked for 25 years and only broke in January

Some bonus archaeology while diagnosing this, in case it changes how the fix is framed.

`git blame` on the four gate lines:

| Server | File:Line | Introducing commit |
|---|---|---|
| Telnet | `MainFormUnit.cpp:357` | `d0252720e` (2026-05-21, "sbbsctrl: Add 'Log to Disk' option for Terminal and Web servers", resolves #1108) |
| Mail | `MainFormUnit.cpp:524` | `7e3e47141` (2000-10-10, "Initial check-in: v3.00c alpha code for Win32") |
| FTP | `MainFormUnit.cpp:620` | `7e3e47141` (2000-10-10, "Initial check-in: v3.00c alpha code for Win32") |
| Web | `MainFormUnit.cpp:717` | `d0252720e` (2026-05-21, same as Telnet) |

So the `&& XxxStop->Enabled` half of the gate for **Mail and FTP** is original 2000-era code. It worked in practice for 25+ years because of an accident of the surrounding code: the old `xxx_set_state` callbacks had a `switch` with **only two explicit cases** (`SERVER_STOPPED` and `SERVER_READY`). Every other transitional state (init, "terminating, waiting for clients to disconnect", etc.) fell through and left `XxxStop->Enabled` at its previous value  i.e. `true` the whole way through a graceful shutdown, only flipping false on the final `SERVER_STOPPED` callback, which fires *after* the per-server thread emits its summary line. So the gate happened to be open at exactly the right moment.

That changed on 2026-01-12 in commit `f65fd89a1` ("Resolve crashes during graceful server termination(s)"). That commit fixed a real bug  VCL controls being touched from background server-thread callbacks after the form was already destroyed  by moving all control updates out of the state callbacks and onto the 2 Hz LogTimer, with the mapping rewritten as flat assignments:

```cpp
MainForm->FtpStop->Enabled = (state == SERVER_READY);
MainForm->FtpRecycle->Enabled = (state == SERVER_READY);
MainForm->FtpPause->Enabled = (state == SERVER_READY);
```

Correct for its stated purpose, but it tightened `XxxStop->Enabled` from "best-effort proxy for is-server-running" to strict `state == SERVER_READY`. The moment shutdown begins, state leaves `SERVER_READY`, the next LogTimer tick flips `XxxStop->Enabled` to `false`, and the gate slams shut well before the `#### XxxX Server thread terminated (...)` line is logged.

**Telnet and Web** weren't a regression  `d0252720e` (May 2026, resolves #1108) added disk-logging to those two servers for the first time and *copied the Mail/FTP gate pattern verbatim*, inheriting the broken semantics on arrival.

### Implication for the fix

The suggested fix (drop `&& XxxStop->Enabled` from all four handlers) is still the right call, but it's worth knowing that *the gate itself was never load-bearing*  it was a 25-year-old belt-and-suspenders check that happened to work because of how the old switch left the flag alone during transitions. `f65fd89a1` didn't introduce the gate; it removed the slack that was masking it. So there's no "preserve the historical intent" angle to worry about here  the gate was redundant from the start, and the user's "Log to Disk" preference alone is the correct condition.

 *Authored by Claude (Claude Code), on behalf of @rswindell*
--- SBBSecho 3.37-Linux
 * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)

-----------------------------------------------------------
[Voltar]