• Busy Web/FTP/Mail/Services servers never act on recycle semaphores

    From Rob Swindell@1:103/705 to GitLab issue in main/sbbs on Thu Oct 22 12:25:39 2026
    open https://gitlab.synchro.net/main/sbbs/-/work_items/1295

    A server that always has at least one client connected never recycles. The
    Web, FTP, Mail and Services servers check their recycle semaphores (`ctrl/recycle`, `recycle.<server>`, changed `.ini` files, and the `recycle_now` signal from MQTT/sbbsctrl) only when no sessions are active:

    | Server | Recycle check is skipped unless |
    |---|---|
    | Web (`websrvr.cpp`, `web_server()`) | `thread_count <= 2` (+1 with the HTTP logging thread) |
    | FTP (`ftpsrvr.cpp`, `ftp_server()`) | `thread_count <= 1` |
    | Mail (`mailsrvr.cpp`, `mail_server()`) | `thread_count <= 1` (+1 with sendmail) |
    | Services (`services.cpp`, `services_thread()`) | `active_clients() == 0` and no threads pending start |

    The terminal server checks its semaphores unconditionally and flags busy
    nodes to rerun instead, so it is not affected.

    A public web server is rarely idle: crawlers alone keep dozens of sessions
    open around the clock. On such a system a recycle request is never acted
    on, so anything that relies on a recycle silently does not take effect:

    - **TLS certificate renewal.** `letsyncrypt.js` writes the new
    `ctrl/ssl.cert` and touches `ctrl/recycle`. The Web Server keeps serving
    the old certificate from memory until it is restarted, so an unattended
    renewal does not prevent the certificate from expiring.
    - **Configuration changes** (`sbbs.ini`, `web_handler.ini`, `mime_types.ini`,
    `mailproc.ini`, `services.ini`, etc.) are never loaded.

    Nothing is logged, so the sysop sees no sign that the request is pending.

    Observed 2026-10-22 on a busy Linux web server (`sbbs d w!`, about 30
    clients and 65 threads at any moment): `letsyncrypt.js` renewed the
    certificate and touched `ctrl/recycle`; the services, FTP, terminal and
    mail servers (another `sbbs` process, idle at the time) logged "Recycle semaphore file detected" within 15 seconds, while the Web Server never did
    and continued serving the previous certificate.

    #236 described this (check semaphores even when in use, and stop accepting
    new connections once a terminate or recycle is flagged). Its fix made the **shutdown** semaphore unconditional; the **recycle** checks remain behind
    the idle test.

    Possible approaches:

    1. Check recycle semaphores on every pass; once one is detected, log it,
    stop accepting new connections, let current sessions finish, and
    recycle. A drain time limit is needed, after which remaining sessions
    are dropped, or a single long download or hung script holds the server
    (and refuses all new connections) indefinitely.
    2. Independently, reload the TLS certificate (`ctrl/ssl.cert` mtime) without
    a recycle, so certificate renewal never needs to refuse connections.

    At minimum, log once when a recycle request is detected but deferred
    because sessions are active.

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