open
https://gitlab.synchro.net/main/sbbs/-/issues/1172
## Summary
The whole-base lock (`smb_lock`/`smb_unlock`/`smb_islocked` in `src/smblib/smblib.c`) is an **existence-only semaphore** (`<base>.lock`) with several race / recovery weaknesses. These were surfaced while root-causing the 2026-06-23 `mail`-base loss; the lock was *not* the direct cause of that incident, but the issues below are real and worth hardening — especially for multi-host (SMB-shared) bases like Vertrauen's, where the same base is opened from a Linux mail server and a Windows host concurrently.
## Issues
1. **In-flight openers are not drained.** `smb_lock()` simply creates `<base>.lock`. `smb_open()` honours it only by *refusing new opens* (waits `retry_time`, then `SMB_ERR_TIMEOUT`). A process that already had the base open when the lock was taken keeps its handles — so a maintenance op (e.g. `smbutil pack`) can rename the base files out from under an in-flight reader/writer.
2. **No staleness / ownership / crash recovery.** `smb_islocked()` is a bare `access("<base>.lock")` existence check — no PID, host, or timestamp. If a process holding the lock is `SIGKILL`ed (or dies before `smb_unlock`), the `.lock` file persists and **blocks every opener indefinitely** until someone removes it by hand. Conversely a clean error-exit releases the lock and immediately exposes any half-finished on-disk state.
3. **Maintenance runs without the base lock.** The `m` (maintain) command in `smbutil.c` takes only `smb_locksmbhdr()` (a byte-range lock on the `.shd`), **not** the full `smb_lock()` base lock that `p`/`D`/`L` take. So maintenance rewrites/truncates the index while other processes may have the base open.
## Possible improvements
- Write `pid@host` + timestamp into the `.lock` file so `smb_islocked()` can detect and reclaim stale locks (auto-expire after a timeout).
- Either have `smb_lock()` wait for existing handles to drain, or clearly document that callers must quiesce all writers (stop the mail/other servers) before a destructive maintenance op — and make `smbutil` warn when the base is in use.
- Take the full base lock for the `m` (maintain) operation, not just the SMB header lock.
— *Authored by Claude (Claude Code), on behalf of @rswindell*
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)