PgDog version
v0.1.57 (main 7594279; session and transaction modes)
Description
A legal extended-protocol pipeline containing two executed queries, a portal Describe, and one Sync completes directly but stalls through PgDog after the first two results. split_extended() inserts Flush after each Execute, then emits the trailing portal Describe and original Sync as separate requests. PostgreSQL does not send the Describe response until Flush or Sync (pq_flush()), but client_messages() waits for that response before it processes the separated Sync. The wait survives frontend close, leaving the backend checked out in both tested pool modes; repeated requests can exhaust the affected pool.
Reproduce
Install psycopg[binary] and run:
#!/usr/bin/env python3
import time
from psycopg.pq import ExecStatus, PGconn
TIMEOUT = 3.0
def run(label: str, dsn: str) -> None:
conn = PGconn.connect(dsn.encode())
try:
if conn.status != 0:
raise RuntimeError(conn.error_message.decode(errors="replace"))
conn.enter_pipeline_mode()
conn.send_query_params(b"SELECT 1", None)
conn.send_query_params(b"SELECT 2", None)
conn.send_describe_portal(b"")
conn.pipeline_sync()
statuses = []
deadline = time.monotonic() + TIMEOUT
while time.monotonic() < deadline:
conn.consume_input()
if not conn.is_busy():
result = conn.get_result()
if result is None:
if statuses and statuses[-1] == "PIPELINE_SYNC":
break
time.sleep(0.01)
continue
statuses.append(ExecStatus(result.status).name)
else:
time.sleep(0.01)
if statuses and statuses[-1] == "PIPELINE_SYNC":
break
print(f"{label}: statuses={statuses}")
finally:
try:
conn.finish()
except Exception:
pass
run("direct", DIRECT_DSN)
run("pgdog", PGDOG_DSN)
Expected behavior
Both endpoints should print:
direct: statuses=['TUPLES_OK', 'TUPLES_OK', 'COMMAND_OK', 'PIPELINE_SYNC']
pgdog: statuses=['TUPLES_OK', 'TUPLES_OK', 'COMMAND_OK', 'PIPELINE_SYNC']
Actual behavior
The reproducer prints:
direct: statuses=['TUPLES_OK', 'TUPLES_OK', 'COMMAND_OK', 'PIPELINE_SYNC']
pgdog: statuses=['TUPLES_OK', 'TUPLES_OK']
The trailing Describe response and pipeline synchronization result never arrive.
PgDog version
v0.1.57(main7594279; session and transaction modes)Description
A legal extended-protocol pipeline containing two executed queries, a portal
Describe, and oneSynccompletes directly but stalls through PgDog after the first two results.split_extended()insertsFlushafter eachExecute, then emits the trailing portalDescribeand originalSyncas separate requests. PostgreSQL does not send theDescriberesponse untilFlushorSync(pq_flush()), butclient_messages()waits for that response before it processes the separatedSync. The wait survives frontend close, leaving the backend checked out in both tested pool modes; repeated requests can exhaust the affected pool.Reproduce
Install
psycopg[binary]and run:Expected behavior
Both endpoints should print:
Actual behavior
The reproducer prints:
The trailing
Describeresponse and pipeline synchronization result never arrive.