From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20030925
Description of problem:
When not all results are retrieved from a DataQuery with next(), and
close() is not called,
com.redhat.persistence.engine.rdbms.ResultCycle.finalize() can close
the database Connection when it is invoked. This results in a
"java.sql.SQLException: Connection has been closed" when another
thread is currently using this connection.
See the attached log for an example where a thread gets a Connection
object, the finalizer thread closes that Connection object, and the
first thread dies with an exception trying to use the Connection it
Version-Release number of selected component (if applicable):
Steps to Reproduce:
This is hard to reproduce because garbage collection is unpredictable.
But on a customer's development system, the error could be reproduced
by clicking around in the UI for some time.
1. Call DataQuery.next() for a result set with more than one row
2. Don't call close(), but make sure that the JVM can garbage collect
the DataQuery object (by using a local variable).
3. Do some more work, including database accesses.
Expected Results: Either the ResultCycle finalizer should not close
the Connection, or it should make sure that the connection is not used
before closing it, or we should update the DataQuery documentation and
tell people that close() *has* to be called when not all rows are
retrieved. The latter is what I have done for now.
This happens with the 6.0 code from Perforce. It did not happen with
the release version of 6.0. (Although one cannot be sure with an error
which depends on a certain object being garbage collected at a certain
Created attachment 95714 [details]
Example of how the finalizer thread closes the connection used by another
Created attachment 95759 [details]
JSP to reproduce the bug
Actually, the bug is easy to reproduce, thanks to System.gc() and
runFinalization(). See the attached JSP.
Note that the "Connection has been closed" exception you will get comes from
the BaseServlet class. That's because it tries to abort the transaction after
catching the exception thrown in the JSP, and while doing so, throws an
exception itself. If you comment the "transaction.abort()" in
BaseServlet.internalService(), you will get the original exception from
Another interesting thing about the JSP is the behaviour when you add a call to
users.close() or remove the if block altogether. In this case, you will get a
null pointer exception in the finalize method of _test_22dfinalize__jsp. Not
sure why that happens.
carsten: is this project-critical? we're aggressively triaging for QU,
so target for 6.0.2 unless you say otherwise.
No, it is not project-critical. We have added close() calls for all
DataQuery objects where we don't retrieve all rows.
Unfortunately, fixing this by adding close() calls did not work as
well as expected. We still encounter the error sporadically, and have
enabled debug logging for ResultCycle to track down the places where
DataQueries are not closed. But that's a slow process.
It would really be helpful if this bug were fixed in the persistence
In theory, this shouldn't be happening.
In practice, it is. Retarget based on Carsten's comments for 6.0.1,
but need to investigate and determine what the root cause is before
deciding whether or not a fix can be done for 6.0.1.
Changes which add close() calls to core and cms code: 37948, 37950
This bug was caused by faulty integration from dev to 6.0.x. Change
36462 on 6.0.x added result set closing functionality that interacted
poorly with the com.arsdigita.db.* jdbc wrappers that did the same
thing . Change 38190 reverts 36462. The test jsp works now.