Uploaded image for project: 'Confluence Data Center'
  1. Confluence Data Center
  2. CONFSERVER-12201

Race condition issue with DefaultHibernateUser

XMLWordPrintable

      While debugging an issue in our custom authenticator that creates and updates user accounts during logins, I found something that appears to be a bug in how DefaultHibernateUser objects are being handled (and cached?) in confluence.

      It looks like the DefaultHibernateUser objects are being cached with its (groups) collections attached with the hibernate session that performed an operation on the object recently (in a different thread). When another thread with a new hibernate session attempts to update such a user instance the exception below is thrown. We are not passing the objects between threads via http session or in any other way. Each thread obtains an instance of the user class via userAccessor.

      Steps to reproduce:

      You need two threads that get the user instance via an instance of UserAccessor, and call UserAccessor#saveUser(confUser).

      1. thread 1 opens a hibernate session
      2. thread 2 opens a hibernate session
      3. thread 1 fetches a user
      4. thread 1 saves the user
      5. thread 2 fetches the same user as thread #1
      6. thread 2 saves the user
      7. the exception is thrown in thread 2
      8. thread 1 closes the hibernate session - this is important, it seems that if the session was closed before thread 2 called saveUser, everything would be ok
      9. thread 2 closes the hibernate session

      The exception:

      org.springframework.orm.hibernate.HibernateSystemException: Illegal attempt to associate a collection with two open sessions; 
      nested exception is net.sf.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
      Caused by: net.sf.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
              at net.sf.hibernate.collection.PersistentCollection.setCurrentSession(PersistentCollection.java:257)
              at net.sf.hibernate.impl.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:38)
              at net.sf.hibernate.impl.AbstractVisitor.processValue(AbstractVisitor.java:69)
              at net.sf.hibernate.impl.AbstractVisitor.processValues(AbstractVisitor.java:36)
              at net.sf.hibernate.impl.AbstractVisitor.process(AbstractVisitor.java:91)
              at net.sf.hibernate.impl.SessionImpl.doUpdateMutable(SessionImpl.java:1466)
              at net.sf.hibernate.impl.SessionImpl.doUpdate(SessionImpl.java:1480)
              at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1403)
              at org.springframework.orm.hibernate.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:604)
              at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:370)
              at org.springframework.orm.hibernate.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:601)
              at com.atlassian.user.impl.hibernate.HibernateUserManager.saveUser(HibernateUserManager.java:171)
              at com.atlassian.user.impl.cache.CachingUserManager.saveUser(CachingUserManager.java:143)
              at com.atlassian.user.impl.delegation.DelegatingUserManager.saveUser(DelegatingUserManager.java:144)
              at bucket.user.DefaultUserAccessor.saveUser(DefaultUserAccessor.java:224)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296)
              at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177)
              at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
              at com.atlassian.spring.interceptors.SpringProfilingInterceptor.invoke(SpringProfilingInterceptor.java:20)
              at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
              at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
              at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
              at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
              at $Proxy22.saveUser(Unknown Source)
              at com.sun.dse.wikis.auth.ConfluenceUserManager$1.doInHibernate(ConfluenceUserManager.java:96)
              at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:370)
              at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:337)
              at com.sun.dse.wikis.auth.ConfluenceUserManager.updateUser(ConfluenceUserManager.java:79)
              at com.sun.dse.wikis.auth.SsoFilter.doFilter(SsoFilter.java:124)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:217)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
              at com.atlassian.confluence.util.ClusterHeaderFilter.doFilter(ClusterHeaderFilter.java:35)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:217)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
              at org.springframework.orm.hibernate.support.OpenSessionInV
      

              matt@atlassian.com Matt Ryall
              15d9a6950818 Igor Minar
              Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: