merge origin/main (779 commits) into ethie/pm-clean
Branch semantics kept where main and PM disagree: update_cmd_deps.py, constraints-termux.txt, the Electron update-api-check module and the post-swap hand-off test stay deleted; the pending-fleet-restart catch-up and the local_runtime tag/download ladder stay retired (PM owns engines). Ported from main onto the branch's shape: profile_scoped_chore for the auto-archive and plugin-update housekeeping chores, the local-runtime cross-process boot lock and residency cap, the checkpoint tmp_pack sweep, the cua daemon-liveness status probe, the remote-served Desktop update flag (posix.sh / windows.ps1), sign-in for env-pinned remote gateways (urlDisabled on RemoteSetupFields), the uvloop extra split (uvicorn without [standard]), and the umask-scoping spawn test. uv.lock regenerated with pm.build_env --lock-only; new utf-8 reads from main switched to utf-8-sig (check-windows-footguns).
This commit is contained in:
@@ -52,6 +52,7 @@ from hermes_state_profile_repair import SessionProfileRepairMixin
|
||||
from hermes_state_schema import SessionSchemaMixin
|
||||
import hermes_state_holders as _state_holders
|
||||
import hermes_state_lockguard as _lockguard
|
||||
from hermes_state_lockowners import log_write_lock_holders
|
||||
from hermes_state_dbfile import (
|
||||
_connect_tracked_db, _fd_is_truly_unlinked, _prepare_connection_retirement,
|
||||
_read_sqlite_application_id, _stat_sqlite_sidecar_identity,
|
||||
@@ -798,6 +799,7 @@ class SessionDB(
|
||||
self._close_connection_quietly(self._conn)
|
||||
now = time.monotonic()
|
||||
if now >= deadline:
|
||||
log_write_lock_holders(self.db_path, self._WRITE_PATIENCE_S)
|
||||
raise
|
||||
jitter = random.uniform(self._WRITE_RETRY_SLOW_MIN_S, self._WRITE_RETRY_SLOW_MAX_S)
|
||||
time.sleep(min(jitter, max(deadline - now, 0.001)))
|
||||
@@ -1016,7 +1018,10 @@ class SessionDB(
|
||||
if "locked" in err_msg or "busy" in err_msg:
|
||||
if self._sleep_before_write_retry(deadline, patience_s):
|
||||
continue
|
||||
# Say what actually happened, not disk/permission damage.
|
||||
# Say what actually happened, not disk/permission damage. The holder goes to
|
||||
# the log, not the message: classify_persistence_error() buckets by phrase and
|
||||
# a holder's argv (a worktree named fix-corrupt-db) would flip the bucket.
|
||||
log_write_lock_holders(self.db_path, patience_s)
|
||||
raise sqlite3.OperationalError(
|
||||
f"database is locked (another Hermes process held the "
|
||||
f"state.db write lock for over {patience_s:.0f}s — "
|
||||
@@ -1040,7 +1045,8 @@ class SessionDB(
|
||||
"not a database" in err_msg or is_malformed_db_error(exc)
|
||||
or self._is_fts_write_corruption_error(exc)
|
||||
):
|
||||
self._raise_if_db_replaced()
|
||||
with self._lock:
|
||||
self._raise_if_db_replaced()
|
||||
# Corrupt FTS shadow tables fail every write via the sync triggers while canonical
|
||||
# rows are intact: detach the derived indexes atomically and retry (never rebuild here).
|
||||
if self._enter_fts_fail_open(exc):
|
||||
|
||||
Reference in New Issue
Block a user