Statement.cancel() may cancel queries in the future - Mailing list pgsql-jdbc

From Oliver Jowett
Subject Statement.cancel() may cancel queries in the future
Date
Msg-id 20030915070801.GD23844@opencloud.com
Whole thread Raw
Responses Re: Statement.cancel() may cancel queries in the future  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-jdbc
With a CVS HEAD driver, this code intermittently fails:

    public void testCancel() throws Exception {
        Connection con = TestUtil.openDB();
        Statement stmt = con.createStatement();
        for (int i = 0; i < 100; ++i) {
            stmt.executeQuery("select version()").close();

                        // At this point, we are not running a query
                        // so cancel() should be a no-op.
            stmt.cancel();
        }
    }

with:

    [junit] java.sql.SQLException: ERROR:  Query was cancelled.
    [junit]     at org.postgresql.core.QueryExecutor.executeV2(QueryExecutor.java:289)
    [junit]     at org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:105)
    [junit]     at org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:43)
    [junit]     at org.postgresql.jdbc1.AbstractJdbc1Statement.execute(AbstractJdbc1Statement.java:522)
    [junit]     at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:48)
    [junit]     at org.postgresql.jdbc1.AbstractJdbc1Statement.execute(AbstractJdbc1Statement.java:288)
    [junit]     at org.postgresql.test.jdbc2.MiscTest.testCancel(MiscTest.java:111)

(you may need to run it a few times to see this, it's intermittent).

I'm guessing that what's happening here is that we have:

  send query #1 to backend instance A
  receive results
  open new connection to backend instance B
  send cancel on new connection
  close new connection

  send query #2 to backend instance A
   <cancel is delivered to A>
  query #2 gets cancelled

I've tried adding an in-progress-query flag to the Statement impl and have
cancel() only actually send the cancel if there is an outstanding query, and
this seems to work ok for the above case. However I don't think this handles
the case where we complete the query and start a new one, just after sending
a cancel but before the cancel is delivered, i.e.:

  thread 1: send query #1 to backend
  thread 2: send cancel request
  thread 1: query completes without being cancelled
   (*)
  thread 1: send query #2 to backend
   <cancellation request arrives>
  thread 1: query #2 gets cancelled

We want to block thread 1 at the point marked (*) until we know the cancel
has been processed and it is safe to send another query. However, looking at
the backend code query-cancel is implemented by B sending a signal to A, and
if A is not executing a query the signal is silently eaten. So I'm not sure
how to eliminate this race as we have no way of working out when the signal
has arrived in the above case.

Anyone have ideas on how to handle this?

-O

pgsql-jdbc by date:

Previous
From: Paul Thomas
Date:
Subject: Re: BEA Weblogic 8.1?
Next
From: Malcolm Warren
Date:
Subject: Re: Bug #814