test_bug19520.txt
text/plain
Filename: test_bug19520.txt
Type: text/plain
Part: 1
#!/bin/bash
#
# Reproducer for BUG #19520: PANIC when concurrently manipulating
# stored procedures with track_functions = all (or pl).
#
# On an unfixed build this PANICs. On a fixed build the server survives.
set -e
PGPORT="${1:-5432}"
PGDATABASE="postgres"
PGUSER="${USER:-postgres}"
N_DDL=10 # number of DROP/CREATE/CALL workers
N_CALL=20 # number of CALL-only workers
ITERATIONS=3000 # iterations per worker
export PGPORT PGDATABASE PGUSER
echo "=== BUG #19520 reproducer ==="
echo "Port: $PGPORT | DDL workers: $N_DDL | CALL workers: $N_CALL"
echo "Iterations per worker: $ITERATIONS"
echo ""
# Verify the server is reachable
if ! psql -Xc "SELECT 1" > /dev/null 2>&1; then
echo "ERROR: Cannot connect to PostgreSQL on port $PGPORT."
echo "Make sure the server is running with:"
echo " track_functions = 'all' (or 'pl')"
exit 1
fi
# Check track_functions setting
TF=$(psql -XtAc "SHOW track_functions")
if [ "$TF" = "none" ]; then
echo "ERROR: track_functions = 'none'. Must be 'pl' or 'all'."
exit 1
fi
echo "track_functions = '$TF'"
# Create the initial procedure
psql -Xc "CREATE OR REPLACE PROCEDURE proc_race_test()
LANGUAGE plpgsql AS \$\$ BEGIN END; \$\$;" 2>/dev/null || true
PIDS=()
# Generate a SQL script for DDL workers (persistent connection, tight loop)
DDL_SQL=$(mktemp)
for j in $(seq 1 $ITERATIONS); do
cat >> "$DDL_SQL" <<'EOF'
DROP PROCEDURE IF EXISTS proc_race_test;
CREATE OR REPLACE PROCEDURE proc_race_test() LANGUAGE plpgsql AS $$ BEGIN END; $$;
CALL proc_race_test();
EOF
done
# Generate a SQL script for CALL workers (persistent connection, tight loop)
CALL_SQL=$(mktemp)
for j in $(seq 1 $ITERATIONS); do
echo "CALL proc_race_test();" >> "$CALL_SQL"
done
# Launch DDL workers using persistent psql sessions
for i in $(seq 1 $N_DDL); do
psql -X -f "$DDL_SQL" > /dev/null 2>&1 &
PIDS+=($!)
done
# Launch CALL-only workers using persistent psql sessions
for i in $(seq 1 $N_CALL); do
psql -X -f "$CALL_SQL" > /dev/null 2>&1 &
PIDS+=($!)
done
echo "Launched ${#PIDS[@]} background workers (persistent connections). Waiting..."
echo "(On an unfixed build the server will PANIC; on a fixed build it survives.)"
echo ""
# Wait for all workers
for pid in "${PIDS[@]}"; do
wait "$pid" 2>/dev/null || true
done
# Cleanup temp files
rm -f "$DDL_SQL" "$CALL_SQL"
echo ""
echo "All workers finished."
# Check if the server is still alive
if psql -Xc "SELECT 1" > /dev/null 2>&1; then
echo "PASS: Server is still running - no PANIC occurred."
exit 0
else
echo "FAIL: Server is down - likely hit the PANIC."
echo "Check the server log for:"
echo ' PANIC: cannot abort transaction xxx, it was already committed'
exit 1
fi