Uploaded image for project: 'JBoss Enterprise Application Platform 4 and 5'
  1. JBoss Enterprise Application Platform 4 and 5
  2. JBPAPP-10515

[HHH-7910] hibernate and its integration in the application server can cause an unsafe use of the session

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Do
    • Icon: Major Major
    • None
    • EAP_EWP 5.1.2
    • Hibernate
    • None
    • NEW

      https://hibernate.onjira.com/browse/HHH-7910

      If a transaction times out while fetching, the thread that is fetching will throw the following exception: org.hibernate.AssertionFailure: possible non-threadsafe access to the session.

      It is indeed a non-threadsafe access to the session, but triggered indirectly by hibernate itself.

      What happens is that when an entity manager gets created, it will register with the current jta transaction:

      Thread [WorkerThread#0[10.23.132.245:61617]] (Suspended (entry into method joinTransaction in AbstractEntityManagerImpl))	
      	EntityManagerImpl(AbstractEntityManagerImpl).joinTransaction(boolean) line: 436	
      	EntityManagerImpl(AbstractEntityManagerImpl).postInit() line: 82	
      	EntityManagerImpl.<init>(SessionFactory, PersistenceContextType, PersistenceUnitTransactionType, boolean, Class, Map) line: 62	
      	EntityManagerFactoryImpl.createEntityManager(Map) line: 40	
      	EntityManagerFactoryImpl.createEntityManager() line: 35	
      

      as a result, a jta synchronization gets registered with code like:

                  public void afterCompletion(int status)
                  {
                      try
                      {
                          if(STATUS_ROLLEDBACK == status && transactionType == PersistenceUnitTransactionType.JTA && session.isOpen())
                              session.clear();
      
      

      When the transaction times out, the after completion will get called, which will clear the session, like in this stack (reaper thread):

      Daemon Thread [Thread-47] (Suspended (entry into method clear in StatefulPersistenceContext))	
      	StatefulPersistenceContext.clear() line: 202	
      	SessionImpl.clear() line: 284	
      	AbstractEntityManagerImpl$1.afterCompletion(int) line: 526	
      	SynchronizationImple.afterCompletion(int) line: 123	
      	AtomicAction(TwoPhaseCoordinator).afterCompletion(int) line: 389	
      	AtomicAction(TwoPhaseCoordinator).cancel() line: 116	
      	AtomicAction(AtomicAction).cancel() line: 213	
      	TransactionReaper.doCancellations() line: 446	
      	ReaperWorkerThread.run() line: 91	
      

      If you are in the middle of fetching, such as in the following stack, then you will fail on the assertion:

      Thread [WorkerThread#0[10.23.132.245:61252]] (Suspended)	
      	TwoPhaseLoad.initializeEntity(Object, boolean, SessionImplementor, PreLoadEvent, PostLoadEvent) line: 121	
      	QueryLoader(Loader).initializeEntitiesAndCollections(List, Object, SessionImplementor, boolean, Object) line: 1030	
      	QueryLoader(Loader).initializeEntitiesAndCollections(List, Object, SessionImplementor, boolean) line: 987	
      	QueryLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 896	
      	QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 298	
      	QueryLoader(Loader).doList(SessionImplementor, QueryParameters, ResultTransformer) line: 2455	
      	QueryLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2440	
      	QueryLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line: 2316	
      	QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2311	
      	QueryLoader.list(SessionImplementor, QueryParameters) line: 414	
      	QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 364	
      	HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 196	
      	SessionImpl.list(String, QueryParameters) line: 1192	
      	QueryImpl.list() line: 102	
      	QueryImpl.getResultList() line: 94	
      ...
      

      This unsafe access to the session occurs because the fetch is happening and, in parallel, the reaper clears the session.

      An appropriate implementation would just position a flag using some synchronized code in the session from the reaper, and let the thread that uses the session consult the flag and take appropriate actions, such as clearing the session and throwing an exception with a clear message.

              brmeyer_jira Brett Meyer (Inactive)
              rhn-support-sappleton Shaun Appleton
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: