diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c index b35e533b66..ab1ef03604 100644 --- a/src/test/isolation/isolationtester.c +++ b/src/test/isolation/isolationtester.c @@ -550,8 +550,53 @@ run_permutation(TestSpec * testspec, int nsteps, Step ** steps) for (i = 0; i < nsteps; i++) { Step *step = steps[i]; + PGconn *conn = conns[1 + step->session]; - if (!PQsendQuery(conns[1 + step->session], step->sql)) + if (waiting != NULL && step->session == waiting->session) + { + PGcancel *cancel; + PGresult *res; + int j; + + /* + * This permutation is invalid: it can never happen in real life. + * + * A session is blocked on an earlier step (waiting) and no further + * steps from this session can run until it is unblocked, but it + * can only be unblocked by running steps from other sessions. + */ + fprintf(stderr, "invalid permutation detected\n"); + + /* Cancel the waiting statement from this session. */ + cancel = PQgetCancel(conn); + if (cancel != NULL) + { + char buf[256]; + + PQcancel(cancel, buf, sizeof(buf)); + + /* Be sure to consume the error message. */ + while ((res = PQgetResult(conn)) != NULL) + PQclear(res); + + PQfreeCancel(cancel); + } + + /* + * Now we really have to complete all the running transactions to + * make sure teardown doesn't block. + */ + for (j = 1; j < nconns; j++) + { + res = PQexec(conns[j], "ROLLBACK"); + if (res != NULL) + PQclear(res); + } + + goto teardown; + } + + if (!PQsendQuery(conn, step->sql)) { fprintf(stdout, "failed to send query for step %s: %s\n", step->name, PQerrorMessage(conns[1 + step->session])); @@ -590,6 +635,7 @@ run_permutation(TestSpec * testspec, int nsteps, Step ** steps) report_error_message(waiting); } +teardown: /* Perform per-session teardown */ for (i = 0; i < testspec->nsessions; i++) {