[
https://issues.apache.org/jira/browse/DERBY-2689?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12501786
]
Bryan Pendleton commented on DERBY-2689:
----------------------------------------
Hi Manish, that is a great point. I think that calling finish() on a
PreparedStatement
doesn't mean that the entire statement is finished off, just that this
particular
activation is finished off. The activations seem to maintain an "inUseCount"
reference count on the statement, and calling finish() for a particular
activation
just decrements the reference count, and only reclaims the entire statement if
the inUseCount has gone to 0.
In the case I looked at in the debugger, however, the inUseCount is nowhere
close
to 0; it is in fact 60. So the statement is not finished, just this particular
activation.
It seems that closing an activation requires that we synchronize on the
statement
in order to decrement the inUseCount, so this means that as part of initializing
a new activation for one statement, we may decide to close an activation for
some other statement, and since there is no inherent ordering to these
reclaimable
activations, we have the situation that one thread which is trying to
initialize an
activation for statement A is trying to close an activation for statement B,
while another
thread which is trying to initialize an activation for statement B is trying to
close
an activation for statement A.
I agree with the assessment that this is a classical deadlock due to a lack of
lock ordering for the synchronization on the various statement objects.
I can see several possibilities:
- don't try to reclaim activations from inside of addActivation (that is,
revert that
part of the DERBY-418 change). This would of course re-introduce that memory
leak.
- Move the code which reclaims activations to some other location, where it is
safer to call, because we aren't calling it while holding any statements
locked.
- Change the code which reclaims activations so that it only closes those
activations which are for the statement that we already have locked, and not
for any other statements. This might render this code much less effective.
- Introduce some sort of ordering of statement objects, and only reclaim
activations for statements which have a higher ordering than ourselves. Since
the statement locks would then be ordered, the code would not deadlock.
I'm sure there are a number of other ways to look at this, I just wanted to add
my thoughts.
> Deadlock with GenericPreparedStatement
> --------------------------------------
>
> Key: DERBY-2689
> URL: https://issues.apache.org/jira/browse/DERBY-2689
> Project: Derby
> Issue Type: Bug
> Components: JDBC
> Affects Versions: 10.2.2.0
> Environment: Windows
> Reporter: Marc Ewert
> Attachments: TestDerbyPreparedStatements.java
>
>
> We encountered two times a deadlock inside of derby. It seems that we can't
> workaround it. The involved two threads are attached, it looks like a
> classical deadlock:
> "Thread-22" daemon prio=6 tid=0x0cdaa400 nid=0x1c0 waiting for monitor entry
> [0x1317f000..0x1317fd4c]
> java.lang.Thread.State: BLOCKED (on object monitor)
> at org.apache.derby.impl.sql.GenericPreparedStatement.finish(Unknown
> Source)
> - waiting to lock <0x052f4d70> (a
> org.apache.derby.impl.sql.GenericPreparedStatement)
> at org.apache.derby.impl.sql.execute.BaseActivation.close(Unknown
> Source)
> at
> org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.addActivation(Unknown
> Source)
> at
> org.apache.derby.impl.sql.execute.BaseActivation.initFromContext(Unknown
> Source)
> at
> org.apache.derby.impl.services.reflect.LoadedGeneratedClass.newInstance(Unknown
> Source)
> at
> org.apache.derby.impl.services.reflect.ReflectGeneratedClass.newInstance(Unknown
> Source)
> at org.apache.derby.impl.sql.GenericActivationHolder.<init>(Unknown
> Source)
> at
> org.apache.derby.impl.sql.GenericPreparedStatement.getActivation(Unknown
> Source)
> - locked <0x05306f88> (a
> org.apache.derby.impl.sql.GenericPreparedStatement)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown
> Source)
> at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown
> Source)
> - locked <0x047beb00> (a org.apache.derby.impl.jdbc.EmbedConnection40)
> at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown
> Source)
> [custom methods]
> "ThreadPoolThread-SyncScheduler-3-1" prio=2 tid=0x0e620400 nid=0xfec waiting
> for monitor entry [0x10a7e000..0x10a7fa14]
> java.lang.Thread.State: BLOCKED (on object monitor)
> at org.apache.derby.impl.sql.GenericPreparedStatement.finish(Unknown
> Source)
> - waiting to lock <0x05306f88> (a
> org.apache.derby.impl.sql.GenericPreparedStatement)
> at org.apache.derby.impl.sql.execute.BaseActivation.close(Unknown
> Source)
> at
> org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.addActivation(Unknown
> Source)
> at
> org.apache.derby.impl.sql.execute.BaseActivation.initFromContext(Unknown
> Source)
> at
> org.apache.derby.impl.services.reflect.LoadedGeneratedClass.newInstance(Unknown
> Source)
> at
> org.apache.derby.impl.services.reflect.ReflectGeneratedClass.newInstance(Unknown
> Source)
> at org.apache.derby.impl.sql.GenericActivationHolder.<init>(Unknown
> Source)
> at
> org.apache.derby.impl.sql.GenericPreparedStatement.getActivation(Unknown
> Source)
> - locked <0x052f4d70> (a
> org.apache.derby.impl.sql.GenericPreparedStatement)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown
> Source)
> at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown
> Source)
> at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown
> Source)
> - locked <0x04225178> (a org.apache.derby.impl.jdbc.EmbedConnection40)
> at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown
> Source)
> [custom methods]
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.