Nice work cracking this down Reka!

Your fix looks fine for me.

On Wed, Jun 24, 2015 at 2:36 PM, Reka Thirunavukkarasu <r...@wso2.com>
wrote:

> Hi
>
> Thought of sharing some details about $subject. So that it might help us
> to identify or debug any issues in future. We faced a thread
> synchronization issue when using Hierarchical locking. The code segment
> below caused the issue:
>
> public TopologyLock getTopologyLockForService(String serviceName, boolean
> forceCreationIfNotFound) {
>         TopologyLock topologyLock =
> serviceNameToTopologyLockMap.get(serviceName);
>         if (topologyLock == null && forceCreationIfNotFound) {
>            * synchronized (TopologyLockHierarchy.class) {*
>                 if (topologyLock == null) {
>                     topologyLock = new TopologyLock();
>                     serviceNameToTopologyLockMap.put(serviceName,
> topologyLock);
>                 }
>             }
>         }
>         return topologyLock;
>     }
>
> If two threads try to initially access this getTopologyLockForService at
> the same time  just after the server startup when try to acquire write
> lock, there would be higher chance that they see the topologyLock as null
> which is a thread local variable as this method is not thread safe. After
> that one thread would enter into synchronized block and add the lock to
> hierarchy and exit. But when the second one executes the synchronized
> block, since it already has the lock as null due to the get operation is
> executed before the synchronized block, it will try to create a lock object
> again and add it to the hierarchy. Due to this lock object got overwritten
> in the map by second thread, when thread one tries to remove the lock from
> the newly created lock object where first thread doesn't hold any lock,
> thread one will fail to remove the lock [1]. Then our ReadWriteLockMonitor
> complains that lock didn't get removed even after 30s [2].
>
> Solution:
>
> Make the method *syncronized* as below:
>
> public *synchronized* TopologyLock getTopologyLockForService(String
> serviceName, boolean forceCreationIfNotFound) {
>         TopologyLock topologyLock =
> serviceNameToTopologyLockMap.get(serviceName);
>         if (topologyLock == null && forceCreationIfNotFound) {
>             topologyLock = new TopologyLock();
>             serviceNameToTopologyLockMap.put(serviceName, topologyLock);
>
>         }
>         return topologyLock;
>     }
>
> This solves the issue that was faced earlier.
>
> Please share your concerns, if the fix has any other impact.
>
> [1] [2015-06-23 17:01:34,524]  WARN
> {org.apache.stratos.common.concurrent.locks.ReadWriteLock} -  System
> warning! Trying to release a lock which has not been taken by the same
> thread: [lock-name] application [thread-id] 131 [thread-name]
> pool-28-thread-6
>
> [2] 2015-06-23 17:02:04,526] ERROR
> {org.apache.stratos.common.concurrent.locks.ReadWriteLockMonitor} -  System
> error, lock has not released for 30 seconds: [lock-name] application
> [lock-type] Write [thread-id] 131 [thread-name] pool-28-thread-6
> [stack-trace]
> java.lang.Thread.getStackTrace(Thread.java:1589)
>
> org.apache.stratos.common.concurrent.locks.ReadWriteLock.acquireWriteLock(ReadWriteLock.java:123)
>
> org.apache.stratos.messaging.message.processor.application.updater.ApplicationsUpdater.acquireWriteLockForApplication(ApplicationsUpdater.java:93)
>
> org.apache.stratos.messaging.message.processor.application.GroupInstanceCreatedProcessor.process(GroupInstanceCreatedProcessor.java:57)
>
> org.apache.stratos.messaging.message.processor.MessageProcessorChain.process(MessageProcessorChain.java:61)
>
> org.apache.stratos.messaging.message.receiver.application.ApplicationsEventMessageDelegator.run(ApplicationsEventMessageDelegator.java:70)
>
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
>
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
> java.lang.Thread.run(Thread.java:745)
>
> org.apache.stratos.common.exception.LockNotReleasedException
>     at
> org.apache.stratos.common.concurrent.locks.ReadWriteLockMonitor.checkTimeout(ReadWriteLockMonitor.java:72)
>     at
> org.apache.stratos.common.concurrent.locks.ReadWriteLockMonitor.run(ReadWriteLockMonitor.java:55)
>     at
> java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
>     at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
>     at
> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
>     at
> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
>     at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
>     at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
>     at java.lang.Thread.run(Thread.java:745)
>
> Thanks,
> Reka
>
>
>
>
> --
> Reka Thirunavukkarasu
> Senior Software Engineer,
> WSO2, Inc.:http://wso2.com,
> Mobile: +94776442007
>
> --
> <%2B94776442007>
> <%2B94776442007>
> Thanks and Regards,
>
> Isuru H.
> <%2B94776442007>
> +94 716 358 048 <%2B94776442007>* <http://wso2.com/>*
>
>
> * <http://wso2.com/>*
>
>
> * <http://wso2.com/>*
>
>
>

Reply via email to