From 2de6e4b3548ba979fe413a5796132fd0e5761f49 Mon Sep 17 00:00:00 2001 From: Andrey Borodin Date: Sat, 22 Aug 2026 20:38:51 +0300 Subject: [PATCH v1] Let isolationtester report connection loss as a step result --- src/test/isolation/isolationtester.c | 45 ++++++++-- .../expected/wait_cleanup_1.out | 86 +++++++++++++++++++ 2 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 src/test/modules/injection_points/expected/wait_cleanup_1.out diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c index e64dc020b18..31e7341a67a 100644 --- a/src/test/isolation/isolationtester.c +++ b/src/test/isolation/isolationtester.c @@ -828,6 +828,7 @@ try_complete_step(TestSpec *testspec, PermutationStep *pstep, int flags) PGresult *res; PGnotify *notify; bool canceled = false; + char *connection_error = NULL; /* * If the step is annotated with (*), then on the first call, force it to @@ -910,9 +911,19 @@ try_complete_step(TestSpec *testspec, PermutationStep *pstep, int flags) */ if (!PQconsumeInput(conn)) { - fprintf(stderr, "PQconsumeInput failed: %s\n", - PQerrorMessage(conn)); - exit(1); + if (PQstatus(conn) != CONNECTION_BAD) + { + fprintf(stderr, "PQconsumeInput failed: %s\n", + PQerrorMessage(conn)); + exit(1); + } + + /* + * Save the error before PQgetResult() adds another complaint + * about attempting to read from the dead socket. + */ + connection_error = pg_strdup(PQerrorMessage(conn)); + break; } if (!PQisBusy(conn)) break; @@ -979,9 +990,19 @@ try_complete_step(TestSpec *testspec, PermutationStep *pstep, int flags) } else if (!PQconsumeInput(conn)) /* select(): data available */ { - fprintf(stderr, "PQconsumeInput failed: %s\n", - PQerrorMessage(conn)); - exit(1); + if (PQstatus(conn) != CONNECTION_BAD) + { + fprintf(stderr, "PQconsumeInput failed: %s\n", + PQerrorMessage(conn)); + exit(1); + } + + /* + * Save the error before PQgetResult() adds another complaint about + * attempting to read from the dead socket. + */ + connection_error = pg_strdup(PQerrorMessage(conn)); + break; } } @@ -1028,7 +1049,7 @@ try_complete_step(TestSpec *testspec, PermutationStep *pstep, int flags) if (sev && msg) printf("%s: %s\n", sev, msg); - else + else if (!connection_error) printf("%s\n", PQresultErrorMessage(res)); } break; @@ -1037,6 +1058,16 @@ try_complete_step(TestSpec *testspec, PermutationStep *pstep, int flags) PQresStatus(PQresultStatus(res))); } PQclear(res); + + /* The connection is dead, so don't ask libpq for another result. */ + if (connection_error) + break; + } + + if (connection_error) + { + printf("%s\n", connection_error); + pg_free(connection_error); } /* Report any available NOTIFY messages, too */ diff --git a/src/test/modules/injection_points/expected/wait_cleanup_1.out b/src/test/modules/injection_points/expected/wait_cleanup_1.out new file mode 100644 index 00000000000..516a428b364 --- /dev/null +++ b/src/test/modules/injection_points/expected/wait_cleanup_1.out @@ -0,0 +1,86 @@ +Parsed test spec with 3 sessions + +starting permutation: wait1 cancel3 noop3 wait2 wakeup3 noop2 detach3 +injection_points_attach +----------------------- + +(1 row) + +step wait1: SELECT injection_points_run('injection-points-wait'); +step cancel3: + SELECT pg_cancel_backend(pid) FROM pg_stat_activity + WHERE wait_event = 'injection-points-wait'; + +step wait1: <... completed> +ERROR: canceling statement due to user request +step cancel3: <... completed> +pg_cancel_backend +----------------- +t +(1 row) + +step noop3: +step wait2: SELECT injection_points_run('injection-points-wait'); +step wakeup3: SELECT injection_points_wakeup('injection-points-wait'); +injection_points_wakeup +----------------------- + +(1 row) + +step wait2: <... completed> +injection_points_run +-------------------- + +(1 row) + +step noop2: +step detach3: SELECT injection_points_detach('injection-points-wait'); +injection_points_detach +----------------------- + +(1 row) + + +starting permutation: wait1 terminate3 noop3 wait2 wakeup3 noop2 detach3 +injection_points_attach +----------------------- + +(1 row) + +step wait1: SELECT injection_points_run('injection-points-wait'); +step terminate3: + SELECT pg_terminate_backend(pid) FROM pg_stat_activity + WHERE wait_event = 'injection-points-wait'; + +step wait1: <... completed> +server closed the connection unexpectedly + This probably means the server terminated abnormally + before or while processing the request. + +step terminate3: <... completed> +pg_terminate_backend +-------------------- +t +(1 row) + +step noop3: +step wait2: SELECT injection_points_run('injection-points-wait'); +step wakeup3: SELECT injection_points_wakeup('injection-points-wait'); +injection_points_wakeup +----------------------- + +(1 row) + +step wait2: <... completed> +injection_points_run +-------------------- + +(1 row) + +step noop2: +step detach3: SELECT injection_points_detach('injection-points-wait'); +injection_points_detach +----------------------- + +(1 row) + -- That's all, folks. May the source be with you.