Bug 49945

Critical

GemStone/S 64 Bit

3.6.3, 3.6.2, 3.6.1, 3.6, 3.5.8, 3.5.7, 3.5.6, 3.5.5, 3.5.4, 3.5.3, 3.5.2, 3.5.1., 3.5

3.6.4

Repository >> allInstances*, and related repository scan operations, have a risk of cache corruption

In versions 3.6, 3.6.1, 3.6.2, and 3.6.3, the C code that implements repository scan primitive 1030 methods (the scan methods that produce allObjects* and related method results as GsBitmaps) contains a timing bug, in which initialization is done before the GcLock is acquired. This may result in old lifetimes of pages being read into the cache, and corrupting the SPC; if this happens, other Gems on the cache may see page cache faults. The highest risk comes if the scan operation has to wait for the GcLock; that is, another process is holding the GcLock when the scan is requested.

In versions 3.5.x, and 3.6.x versions, the C code that implements the repository scan primitive method 896 (listObjects* and similar methods that return results as Array), contain less significant timing issue, that may potentially cause related problems.

Workaround

If you see page cache faults and are using the problematic methods, restart the stone as soon as possible; this should clear the fault. In some cases, you may need to restore from backup and transaction logs to recover.

The risk is low in v3.5.x; while the code includes a potential timing hole, no problems have been reported,

In v3.6, 3.6.1, 3.6.2, or 3.6.3, using methods that invoke primitive 896 is much safer, and it is recommended to use these until it is possible to upgrade to a version in which this bug is fixed.

The problematic primitive, prim 1030, is in Repository>>_scanWithMaxThreads:witForLock:pageBUfSize:percentCpuActiveLimit:scanKind:with: The following methods ultimately use  this primtive:

(If class is not mentioned: method is on class Repository)

  _doScan:fast:with:
    allInstances:
        fastListInstances:toDirectory:
          SortedCollection(class)>>findAllSortedCollectionsForUser:
        listInstances:toDirectory:
      listInstancesToHiddenSet:
    allInstances:threads:
    allObjectsInObjectSecurityPolicies:
      listObjectsInSegments:
    allObjectsInObjectSecurityPolicies:threds:
    allObjectsLargerThan:
    allObjectsLargerThan:threads:
    allReferences:
      listReferences:
      listReferences:withLimit:
        Object>>findReferencesWithLimit:
          Object>>findAllReferences
          Object>>findReferences
    allReferences:threads:
    allReferencesByParentClass:
    fastAllnstances:
      fastListInstancesToHiddenSet:
        listInstancesToHiddenSet:withMaxThreads:maxCpuUsage:
    fastAllObjectsInObjectSecurityPolicies:
    fastAllObjectsLargerThan:
    fastAllReferences:
      fastListReferences:
    fastAllReferencesByParentClass:
    fastAllReferencesToInstancesOfClasses:

Primitive 896,  in Repository>>_scanPomWithMaxThreads:waitForLock:pageBufSize:percentCpuActiveLimit:identSet:limit:scanKind:toDirectory:, have a much lower risk of problems.  The following methods are low risk:

  _listObjectsInObjectSecurityPolicies:limit:scanKind:toDirectory:
    fastListObjectsInObjectSecurityPolicies:toDirectory:
    fastListObjectsInObjectSecurityPolicies:withLimit:
      fastListObjectsInObjectSecurityPolicies:
    fastListObjectsInObjectSecurityPolicyToHiddenSet:
    listObjectsInObjectSEcurityPolicies:toDirectory:
      listObjectsInSegments:toDirectory:
    listObjectsInObjectSecurityPolicies:withLimit:
      listObjectsInObjectSecurityPolicies:
      listObjectsInSegments:withLimit:
    listObjectsInObjectSecurityPolicyToHiddenSet:
      listObjectsInSegmentToHiddenSet:
  allObjectsLargerThan:limit:
  countInstances:withMaxThreads:maxCpuUsage:
    countInstances:
    fastCountInstances:
  listInstances:limit:toDirectory:withMaxThreads:maxCpuUsage:memoryOnly:
    fastListInstances:limit:
      fastListInstances:
    listInstances:limit:
      listInstances:
        Class>>allInstances
        Module>>migrateInstancesTo:
    listInstances:limit:toDirectory:withMaxThreads:maxCpuUsage:
    listInstancesInMemory:
      (Class>>allInstances)
      Class>>instancesInMemory
      Module>>allInstancesInMemory
      Module>>migrateInstancesTo:
    listInstancesInPageOrder:toFile:withMaxThreads:maxCpuUsage:
      fastListInstancesInPageOrder:toFile:
      listInstancesInPageOrder:toFile:


Last updated: 5/2/22