Statement.cancel() may cancel queries in the future

From: Oliver Jowett <oliver(at)opencloud(dot)com>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: Statement.cancel() may cancel queries in the future
Date: 2003-09-15 07:08:04
Message-ID: 20030915070801.GD23844@opencloud.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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

Responses

Browse pgsql-jdbc by date

  From Date Subject
Next Message Malcolm Warren 2003-09-15 08:54:47 Re: Bug #814
Previous Message Paul Thomas 2003-09-14 11:50:21 Re: BEA Weblogic 8.1?