Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-69500

CentralizedThreadLocal may fail to include all elements when calling _toMap method.

    Details

    • Type: Bug
    • Status: Closed
    • Resolution: Duplicate
    • Affects Version/s: 6.2.10 EE GA1, 6.2.X EE, 7.0.0 DXP SP3, 7.0.0 DXP FP15, Master
    • Fix Version/s: None
    • Component/s: Core Infrastructure
    • Labels:

      Description

      The CentralizedThreadLocal class contains a class ThreadLocalMap which in turn has a field of type Entry[]. The Entry class has a field named _next. The ThreadLocalMap may be populated in a way such that some elements exist in _next fields. These elements are not included in the return value from the _toMap method in the outer class.

      From this snippet it is clear that the _next fields are never used to create the return object:

                private static Map<CentralizedThreadLocal<?>, Object> _toMap(
      		ThreadLocalMap threadLocalMap) {
      
      		Map<CentralizedThreadLocal<?>, Object> map = new HashMap<>(
      			threadLocalMap._table.length);
      
      		for (Entry entry : threadLocalMap._table) {
      			if (entry != null) {
      				CentralizedThreadLocal<Object> centralizedThreadLocal =
      					(CentralizedThreadLocal<Object>)entry._key;
      
      				Object value = centralizedThreadLocal.copy(entry._value);
      
      				if (value != null) {
      					map.put(centralizedThreadLocal, value);
      				}
      			}
      		}
      
      		return map;
      	}
      

      Instead it should be something like:

      private static Map<CentralizedThreadLocal<?>, Object> _toMap(
      		ThreadLocalMap threadLocalMap) {
      
      		Map<CentralizedThreadLocal<?>, Object> map = new HashMap<>(
      			threadLocalMap._table.length);
      
      		for (Entry entry : threadLocalMap._table) {
      
      			for (Entry next = entry; next != null; next = next._next) {
       				CentralizedThreadLocal<Object> centralizedThreadLocal =
      					(CentralizedThreadLocal<Object>)next._key;
       
      				Object value = centralizedThreadLocal.copy(next._value);
      
      				if (value != null) {
      					map.put(centralizedThreadLocal, value);
      				}
      			}
      		}
      
      		return map;
      	}
      

      The problem may e.g. cause PermissionThreadLocal.getPermissionChecker() to return null. The scenario is hard to reproduce but I have experienced it. The following test seems to catch the error.

              @Test
      	public void testSetAndToMap() {
      
      		for (int i = 0; i < 10; i++) {
      			CentralizedThreadLocal<Object> centralizedThreadLocal = new CentralizedThreadLocal<>(true);
      			centralizedThreadLocal.set("1");
      
      			centralizedThreadLocal.remove();
      
      			CentralizedThreadLocal<Object> centralizedThreadLocal2 = new CentralizedThreadLocal<>(true);
      			centralizedThreadLocal2.set("2");
      		}
      
      		Map<CentralizedThreadLocal<?>, Object> shortLivedThreadLocals =
      			CentralizedThreadLocal.getShortLivedThreadLocals();
      
      		Assert.assertEquals(10, shortLivedThreadLocals.size());
      	}
      

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  2 years, 49 weeks, 1 day ago

                  Packages

                  Version Package