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: