You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(firewall): serialize rule writes to kill SQLite lock races (#1020)
IptablesConf::updateFirewallRules() looped `$rule->update()` with no mutex
or transaction, so ReloadFirewallAction running in WorkerModelsEvents raced
with WorkerApiCommands writers and tripped "database is locked" (Sentry
MIKOPBX-KMK/MIKOPBX-KMM, 24 events across 3+ installs on 2026.1.223).
Route the batch through BaseActionHelper::executeInTransaction() so it
takes the shared 'db-write' Redis mutex and runs in a single SQLite
transaction. Rules are materialized first and the mutex/transaction is
only entered when there is real work to do — the common no-op path stays
free of Redis round-trips.
Guard the upgrade path with isMutexAvailable(): UpdateSystemConfig calls
updateFirewallRules() during release upgrades, when Redis may not yet be
reachable. The probe forces a real Redis round-trip via isLocked(); on
failure it logs a warning and falls back to direct per-row save(). Upgrade
is single-threaded in that phase, so the fallback cannot race. Probe
failures are not cached — transient Redis outages auto-recover on the
next call.
Also route Firewall SaveRecordAction through executeInTransaction(): it
previously called $db->begin()/commit()/rollback() directly, without the
'db-write' mutex, so it contended with every other writer. Validation
failures now raise \DomainException as a sentinel — the outer catch
preserves the original API contract (individual Phalcon messages pushed
to $res->messages['error'], no extra syslog noise), while infrastructure
errors still flow through handleError().
Verified on boffart.miko.ru (2026.1.233-dev) with 5 parallel PHP stress
workers × 15 iterations + 5 concurrent REST PATCH:
- baseline (pre-fix): 1 ok / 74 fail, 74 PDOException database-locked
- with fix: 75 ok / 0 fail, 0 locks, 5/5 REST 200 OK
- fallback (Redis down): warning logged, direct writes succeeded
Closes#1020
0 commit comments