* Fix debug build: compile error, false-positive abort, and crash DB lock
- psql_debug.c: add forward declaration for psql_do_prepare to fix
conflicting-types compile error (BUILD=debug was broken entirely)
- pfs_debug.c: change pfs_debug_check_lock_order from abort to log-only;
write paths legitimately take file lock before SQL and handle ordering
via psql_trylock()+relock in pfs_reopen_file_for_writing — no actual
deadlock risk, the check was a false positive
- psignal.c/h: add psignal_register_cleanup() hook mechanism; change
panic() to use _exit(1) instead of abort() so all file descriptors are
closed on crash, releasing SQLite WAL POSIX advisory locks immediately
and preventing ASan from hanging the process as a zombie
- psql.c: register psql_panic_cleanup() hook to close the DB on panic
(belt-and-suspenders alongside _exit fd cleanup)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix debug psql_trylock: missing strong override left lockctr unupdated
The weak psql_trylock() stub in psql.c called plocks_trywrlock() directly
without updating lockctr. In the debug build, psql_unlock() asserts
lockctr > 0, so when trylock succeeded (lock acquired, lockctr still 0)
the assert fired with SIGABRT on write ops via pfs_inc_writeid_locked.
Add a strong psql_trylock() override in psql_debug.c that delegates to
psql_do_trylock(), which properly acquires the rwlock and updates lockctr.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add lock ordering assertions for psql_lock → file mutex
* Add missing psql.h include to pfs.h
* Fix debug build conditional compilation for lock ordering assertions
* Fix function declaration order for pfs_debug_check_lock_order
---------
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
The weak/strong symbol approach requires that psql.c undefs the debug
macros to define function implementations. This means functions in psql.c
call psql_lock()/psql_unlock() as functions, not macros.
In debug builds, these must be strong overrides that call the _do_
variants to properly maintain lockctr/rdlockctr. Without these overrides,
the weak stubs are used which don't update counters, causing assertion
failures in psql_unlock().
Added strong overrides in psql_debug.c for:
- psql_lock() -> psql_do_lock(__FILE__, __LINE__)
- psql_rdlock() -> psql_do_rdlock(__FILE__, __LINE__)
- psql_statement() (calls psql_do_lock directly)
Also made psql_statement, psql_start, and all query/prepare functions
weak in psql.c to allow debug overrides.
Fixes#138
Co-authored-by: Levi Neely <lkn@darkstar.example.net>