@@ -550,8 +550,53 @@ run_permutation(TestSpec * testspec, int nsteps, Step ** steps)
550
550
for (i = 0 ; i < nsteps ; i ++ )
551
551
{
552
552
Step * step = steps [i ];
553
+ PGconn * conn = conns [1 + step -> session ];
553
554
554
- if (!PQsendQuery (conns [1 + step -> session ], step -> sql ))
555
+ if (waiting != NULL && step -> session == waiting -> session )
556
+ {
557
+ PGcancel * cancel ;
558
+ PGresult * res ;
559
+ int j ;
560
+
561
+ /*
562
+ * This permutation is invalid: it can never happen in real life.
563
+ *
564
+ * A session is blocked on an earlier step (waiting) and no further
565
+ * steps from this session can run until it is unblocked, but it
566
+ * can only be unblocked by running steps from other sessions.
567
+ */
568
+ fprintf (stderr , "invalid permutation detected\n" );
569
+
570
+ /* Cancel the waiting statement from this session. */
571
+ cancel = PQgetCancel (conn );
572
+ if (cancel != NULL )
573
+ {
574
+ char buf [256 ];
575
+
576
+ PQcancel (cancel , buf , sizeof (buf ));
577
+
578
+ /* Be sure to consume the error message. */
579
+ while ((res = PQgetResult (conn )) != NULL )
580
+ PQclear (res );
581
+
582
+ PQfreeCancel (cancel );
583
+ }
584
+
585
+ /*
586
+ * Now we really have to complete all the running transactions to
587
+ * make sure teardown doesn't block.
588
+ */
589
+ for (j = 1 ; j < nconns ; j ++ )
590
+ {
591
+ res = PQexec (conns [j ], "ROLLBACK" );
592
+ if (res != NULL )
593
+ PQclear (res );
594
+ }
595
+
596
+ goto teardown ;
597
+ }
598
+
599
+ if (!PQsendQuery (conn , step -> sql ))
555
600
{
556
601
fprintf (stdout , "failed to send query for step %s: %s\n" ,
557
602
step -> name , PQerrorMessage (conns [1 + step -> session ]));
@@ -590,6 +635,7 @@ run_permutation(TestSpec * testspec, int nsteps, Step ** steps)
590
635
report_error_message (waiting );
591
636
}
592
637
638
+ teardown :
593
639
/* Perform per-session teardown */
594
640
for (i = 0 ; i < testspec -> nsessions ; i ++ )
595
641
{
0 commit comments