[ https://issues.apache.org/jira/browse/SLING-7447?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Robert Munteanu updated SLING-7447: ----------------------------------- Description: There is a race condition in the {{ThreadLocalCleaner}} initialization code that can lead to the fields not being fully initialized when read. The stack trace is similar to {noformat}Exception in thread "sling-oak-observation-2" java.lang.NullPointerException at org.apache.sling.commons.threads.impl.ThreadLocalCleaner.copy(ThreadLocalCleaner.java:110) at org.apache.sling.commons.threads.impl.ThreadLocalCleaner.saveOldThreadLocals(ThreadLocalCleaner.java:230) at org.apache.sling.commons.threads.impl.ThreadLocalCleaner.<init>(ThreadLocalCleaner.java:155) at org.apache.sling.commons.threads.impl.ThreadPoolExecutorCleaningThreadLocals.beforeExecute(ThreadPoolExecutorCleaningThreadLocals.java:58) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1139) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:748){noformat} Assume that two threads, _T1_ and _T2_ enter the constructor at more or less the same time. The following events can then occur, leading to the above invalid access ||T1||T2|| |check threadLocalsField (is null)| | |invoke initReflectionFields, load threadLocalsField| | | | check threadLocalsField (is not null) | | | invoke saveOldTreadLocals | | | invoke copy | At this point, the {{tableField}} field is null since {{initReflectionFields}} has not yet completed, which leads to the above NPE. _edit_: formatting was: There is a race condition in the {{ThreadLocalCleaner}} initialization code that can lead to the fields not being fully initialized when read. The stack trace is similar to {noformat}Exception in thread "sling-oak-observation-2" java.lang.NullPointerException at org.apache.sling.commons.threads.impl.ThreadLocalCleaner.copy(ThreadLocalCleaner.java:110) at org.apache.sling.commons.threads.impl.ThreadLocalCleaner.saveOldThreadLocals(ThreadLocalCleaner.java:230) at org.apache.sling.commons.threads.impl.ThreadLocalCleaner.<init>(ThreadLocalCleaner.java:155) at org.apache.sling.commons.threads.impl.ThreadPoolExecutorCleaningThreadLocals.beforeExecute(ThreadPoolExecutorCleaningThreadLocals.java:58) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1139) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:748){noformat} Assume that two threads, _T1_ and _T2_ enter the constructor at more or less the same time. The following events can then occur, leading to the above invalid access ||T1||T2|| |check threadLocalsField (is null)| - | |invoke initReflectionFields, load threadLocalsField| - | | - | check threadLocalsField (is not null) | | - | invoke saveOldTreadLocals | | - | invoke copy | At this point, the {{tableField}} field is null since {{initReflectionFields}} has not yet completed, which leads to the above NPE. > Race condition in ThreadLocalCleaner initialization code > -------------------------------------------------------- > > Key: SLING-7447 > URL: https://issues.apache.org/jira/browse/SLING-7447 > Project: Sling > Issue Type: Bug > Components: Commons > Affects Versions: Commons Threads 3.2.14 > Reporter: Robert Munteanu > Assignee: Robert Munteanu > Priority: Blocker > Fix For: Commons Threads 3.2.16 > > > There is a race condition in the {{ThreadLocalCleaner}} initialization code > that can lead to the fields not being fully initialized when read. > The stack trace is similar to > {noformat}Exception in thread "sling-oak-observation-2" > java.lang.NullPointerException > at > org.apache.sling.commons.threads.impl.ThreadLocalCleaner.copy(ThreadLocalCleaner.java:110) > at > org.apache.sling.commons.threads.impl.ThreadLocalCleaner.saveOldThreadLocals(ThreadLocalCleaner.java:230) > at > org.apache.sling.commons.threads.impl.ThreadLocalCleaner.<init>(ThreadLocalCleaner.java:155) > at > org.apache.sling.commons.threads.impl.ThreadPoolExecutorCleaningThreadLocals.beforeExecute(ThreadPoolExecutorCleaningThreadLocals.java:58) > at > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1139) > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) > at java.lang.Thread.run(Thread.java:748){noformat} > Assume that two threads, _T1_ and _T2_ enter the constructor at more or less > the same time. The following events can then occur, leading to the above > invalid access > ||T1||T2|| > |check threadLocalsField (is null)| | > |invoke initReflectionFields, load threadLocalsField| | > | | check threadLocalsField (is not null) | > | | invoke saveOldTreadLocals | > | | invoke copy | > At this point, the {{tableField}} field is null since > {{initReflectionFields}} has not yet completed, which leads to the above NPE. > _edit_: formatting -- This message was sent by Atlassian JIRA (v7.6.3#76005)