Bugs item #620262, was opened at 2002-10-08 16:44
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=376685&aid=620262&group_id=22866

Category: JBossCX
Group: v3.0 Rabbit Hole
Status: Open
Resolution: Fixed
Priority: 5
Submitted By: Marko Strukelj (mstruk)
Assigned to: David Jencks (d_jencks)
Summary: Trying to change Tx in enlist exception

Initial Comment:
When doing very intensive remote calls via statefull 
session, using the database with user managed 
transactions I often get this error:


2002-10-03 15:51:16,000 WARN  
[org.jboss.resource.connectionmanager.LocalTxConnecti
onManager$LocalConnectionEventListener] in Enlisting 
tx, trying to change tx. illegal state: old: 
TransactionImpl:XidImpl [FormatId=257, 
GlobalId=brutus//233, BranchQual=], new: 
TransactionImpl:XidImpl [FormatId=257, 
GlobalId=brutus//234, BranchQual=], cel: 
org.jboss.resource.connectionmanager.LocalTxConnecti
onManager$LocalConnectionEventListener@1f8d0a4
2002-10-03 15:51:16,000 ERROR [STDERR] 
java.lang.IllegalStateException: Trying to change Tx in 
enlist! 
2002-10-03 15:51:16,000 ERROR [STDERR]  at 
org.jboss.resource.connectionmanager.LocalTxConnecti
onManager$LocalConnectionEventListener.enlist
(LocalTxConnectionManager.java:309)
2002-10-03 15:51:16,000 ERROR [STDERR]  at 
org.jboss.resource.connectionmanager.LocalTxConnecti
onManager.managedConnectionReconnected
(LocalTxConnectionManager.java:255)
2002-10-03 15:51:16,000 ERROR [STDERR]  at 
org.jboss.resource.connectionmanager.BaseConnection
Manager2.allocateConnection
(BaseConnectionManager2.java:534)
2002-10-03 15:51:16,000 ERROR [STDERR]  at 
org.jboss.resource.connectionmanager.BaseConnection
Manager2$ConnectionManagerProxy.allocateConnection
(BaseConnectionManager2.java:812)
2002-10-03 15:51:16,000 ERROR [STDERR]  at 
org.jboss.resource.adapter.jdbc.local.LocalDataSource.g
etConnection(LocalDataSource.java:102)


It only happens when there is severe concurent use of 
the database. But it does happen a lot. 


What seems to happen is this:

Thread 1: 

        userTransaction.begin(); 
        Connection c=ds.getConnection();        // lets 
call this Connection1 

// ... use connection 

        c.close(); // close connection 

// now don't commit transaction yet 



        Thread 2: 
                userTransaction.begin(); 
                Connection c=ds.getConnection(); // 
KABOOOM! Exception happens here. 



Exception happened because Connection1 was trying to 
be returned - the same connection that was used by 
another thread.

In the time between returning a connection to the pool 
and calling commit on UserTransaction the same 
connection is checked out to another thread.



I am trying to make an example to reproduce the bug. 
So far the only way I can reproduce it is on my 
production system with full application deployed.


----------------------------------------------------------------------

>Comment By: Marko Strukelj (mstruk)
Date: 2002-10-24 12:12

Message:
Logged In: YES 
user_id=625403


It seems to work now. I don't see the 'Trying to change Tx in 
enlist' exception any more.

I checked out Branch-3_0, built what claimed to be JBoss-
3.0.4RC1, put in the old code that caused exceptions before. 
It runs out of connections now but this is due to GC 
dynamics.

For all I can say, the bug is fixed.



----------------------------------------------------------------------

Comment By: David Jencks (d_jencks)
Date: 2002-10-23 01:25

Message:
Logged In: YES 
user_id=60525

I think there was a race between close and commit checking
if a connection could be returned and returning it to the
pool.  I've added some synchronization to the 3.0 branch to
try to fix this.  Please try it out and see if is fixed,
then I will do something similar in the other branches.

If you are using a later branch please let me know, I will
check in something there for you to test.

Thanks
david jencks

----------------------------------------------------------------------

Comment By: Marko Strukelj (mstruk)
Date: 2002-10-14 16:33

Message:
Logged In: YES 
user_id=625403

Now I finally got to the bottom of this. Turns out the problem 
that the two threads get the same connection from the pool is 
due to connection being returned to the pool twice.

I have a situation where connection is referenced by another 
object (ormsession object that represents an object relational 
mapper). This object is created upon request and it retrieves 
a database connection from a DataSource for its internal use. 
ormsession calls connection.close() in its finalize() and it 
does this through Finalizer thread - bad idea.


Before this happens (or maybe after - I'm not sure) ut.commit
() is done in the thread that got the ormsession before and 
this again causes the managed connection to be returned to 
the pool.

The problem is that the described chain of events causes an 
inconsistent state in InternalManagedConnectionPool. 
Afterwards there are two different MCHolder instances 
referencing the same ManagedLocalConnection instance.

This makes it possible that later that same MC is checked 
out twice.


During this exploration I also realized that I am using the 
connection pool in such a way that "not participating properly 
in this management scheme." condition is always present. I 
have an MBean with its own thread and it is accessing 
DataSource directly without going through interceptors. Doing 
it this way is very convenient for me and it seems to have 
been working properly thus far. It also worked in jboss 2.4.3. I 
hope it stays that way and that future versions of jboss don't 
break this.


The bug on my part was extremely difficult to find. It would be 
a lot easier if InternalManagedConnectionPool threw 
Exception to point out that a thread that's putting the 
connection back is not the one that took it out.

Or maybe we could just do some other check.

InternalManagedConnectionPool.returnConnection()

executes this statement to return managed connection to the 
pool:
        mcs.addLast(new MCHolder(mc));


it could execute something like this instead:

        for (Iterator i = mcs.iterator(); i.hasNext(); )
        {
                MCHolder mch = (MCHolder)i.next();
                if (mch.getMC() == mc) throw new 
RuntimeException();
        }

        mcs.addLast(new MCHolder(mc));


RuntimeException is necessary because method throws no 
Exception - but doing it like this is kind of ugly itself so the 
best thing to do might be to just leave it as it is and change 
nothing.


I am questioning myself now whether this qualifies as a bug 
or not. The fact is that illegal use on my part caused the 
situation to develop. On the other hand I would expect an 
application server or specifically the pools to not make 2 
connections from one no matter how wrong I use it.

So I leave it to you to decide and won't change it to Not-a-Bug 
just yet.



----------------------------------------------------------------------

Comment By: Marko Strukelj (mstruk)
Date: 2002-10-11 16:08

Message:
Logged In: YES 
user_id=625403

Looks like my initial diagnosis was slightly incorrect. 

What I see happening when I put logging at strategic places 
is that two threads try to get the same connection out at the 
same time. One succeeds the other one gets exception.

It must therefore be a synchronization problem.

I'll try to do some more debugging and to find the offending 
spot.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=376685&aid=620262&group_id=22866


-------------------------------------------------------
This sf.net email is sponsored by: Influence the future 
of Java(TM) technology. Join the Java Community 
Process(SM) (JCP(SM)) program now. 
http://ad.doubleclick.net/clk;4729346;7592162;s?http://www.sun.com/javavote
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to