• src/sbbs3/js_user.cpp

    From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Wednesday, November 11, 2026 22:55:01
    https://gitlab.synchro.net/main/sbbs/-/commit/bc5a11bb62e2e9068c1f2c97
    Modified Files:
    src/sbbs3/js_user.cpp
    Log Message:
    js: don't keep user.tab open for the life of a User object

    On Windows, with user.tab on an SMB share served by Samba, a shared
    byte-range lock can stay on the server after it is unlocked: when two
    handles hold a shared lock on the same record and the first to lock is
    the first to unlock, that handle's lock remains until the handle is
    closed. Readers still get the record; every exclusive lock on it fails.

    The User object kept a read-only user.tab descriptor open until it was finalized (4176df9717, 2018-06-07), and its reads have taken shared
    locks since aa673afdf1 (2026-06-02). When its descriptor was the one
    left holding the lock, the record stayed locked against writers for as
    long as the script's context lived. In the web server that includes
    the session's own http_logoff(), which runs before the context is
    destroyed.

    Symptom: when one webv4 user's requests overlapped, their logins and
    logouts each retried lockuserdat() for about 106 seconds and logged
    "!Error -104 writing user data for user #N" or "!ERROR -104 in
    logoutuserdat", and every page that user requested stalled for that
    long.

    Open, read and close the user base for each uncached read instead, so
    a lock left behind lasts no longer than the read. The object still
    caches the record, so this is one more open per re-read, not per
    property. User.close() remains and does nothing.

    Compiled with MSVC only.

    Fixes #1342

    Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>

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