Hi Hannu,
> Measuring the indicators against SQL in the same session, four edge cases
> still report a state that does not match the catalog.
I went back to this with sanitizers, a session generator with a catalog
oracle, and a protocol fuzzer, all on v3 over master 26bd08fb5c. A few things
worth flagging; the four v3 cases are only used here as controls.
Indicator desyncs -- the class is larger than those four. Over 24,000 random
sessions (246,368 oracle checks) the generator found five more mechanisms.
Three are false negatives with a live temporary table (T=0), which a pool
would read as a clean session; two need only one connection:
- CREATE TEMP TABLE t; BEGIN; DROP TABLE t; ROLLBACK -> T=0, but t is back.
- CREATE TEMP TABLE t; BEGIN; DISCARD TEMP; ROLLBACK -> T=0, t is back.
- a SERIALIZABLE COMMIT that drops a temp table and then fails with 40001
-> T=0, the table survives (two sessions).
The ROLLBACK/40001 restore and DISCARD-in-a-block are master's behaviour; what
the patch adds is the indicator not reflecting it. Two more are about what T
counts: a temp type or function created through pg_temp_N (not the pg_temp
alias) leaves T=0, and DROP SCHEMA pg_temp_N CASCADE leaves T=1 with nothing
there. The doc says "temporary tables" while the code counts more kinds of
temp object, so that one depends on which definition you intend. P and l had
no mismatches in the whole run.
ready_for_query_hook, error path: a hook that raises ERROR puts the backend
into a loop that sends ErrorResponse without stopping (about a million in two
seconds here), stays at 100% CPU after the client disconnects, and does not
respond to pg_terminate_backend() or "pg_ctl stop -m fast" -- only SIGKILL
ends it. Might be worth saying in the hook's contract that it must not throw,
or wrapping the call so a thrown error can't recurse through ReadyForQuery.
Compatibility: plain is transparent for libpq 14..master. rich at connect
fails cleanly ("message contents do not agree with length in message type
Z"). But turning rich on mid-session, by SET or by reload, hangs every
unpatched libpq I tried (7 of 7, 14 through master) -- so enabling it on a
connection an old client is already using is not safe. Also, patched libpq
drops the connection once a rich 'Z' is longer than 30,000 bytes (master's
long-message guard doesn't list 'Z'), so a hook with a large payload can trip
that.
Memory: the server was clean under ASan+UBSan across make check,
installcheck-parallel with every session in rich plus a hook on each
ReadyForQuery, the TAP suites, and the 24,000 generator sessions. One
client-side report: PQtrace reads past libpq's input buffer on a malformed
rich 'Z' (fe-trace.c), but master's tracer has the same over-read for a
DataRow, so it's a new instance of an existing pattern rather than something
new to the design.
Happy to share the generator, the minimal repros and the hook test module.
Regards,
Manu