You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2014/09/20 05:17:52 UTC

svn commit: r1626379 - in /uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl: CASImpl.java TypeSystemImpl.java

Author: schor
Date: Sat Sep 20 03:17:51 2014
New Revision: 1626379

URL: http://svn.apache.org/r1626379
Log:
[UIMA-4017] plug possible multi-thread initialization hole

Modified:
    uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java
    uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java

Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java?rev=1626379&r1=1626378&r2=1626379&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java Sat Sep 20 03:17:51 2014
@@ -2283,142 +2283,150 @@ public class CASImpl extends AbstractCas
     if (ts.areBuiltInTypesSetup) {
       return;
     }
-    ts.areBuiltInTypesSetup = true;
-
-    // W A R N I N G (July 2007)
-
-    // C++ code has "hard-wired" the type code numbers for the
-    // built-in types, so you cannot change the order of the types
-    // Also, the complete serialization depends on the type-code numbers
-    // for the client and the server for the built-in types being
-    // the same.
-
-    // The initialization code for types cannot depend on the type system
-    // having already been set up, because, obviously, it isn't set up (yet).
-
-    // It is important to add types in a particular order and to set
-    // ts.xxx<type-name> and ts.xxx<type-name>code values so they are
-    // set before they're used. Some of the add-type logic is written
-    // to depend on the built-in types already having these values set.
-    // For example: addType ( ARRAY_BASE ) calls, eventually,
-    // ts.ll_isPrimitiveType -> ll_isRefType ->ll_getTypeClass -> ll_subsumes
-    // and along the way these are testing / comparing against type codes
-    // for built-in types which need to have been set.
-
-    // Create top type.
-    Type top = ts.addTopType(CAS.TYPE_NAME_TOP);
-    // Add basic data types.
-    Type intT = ts.addType(CAS.TYPE_NAME_INTEGER, top);
-    Type floatT = ts.addType(CAS.TYPE_NAME_FLOAT, top);
-    Type stringT = ts.addType(CAS.TYPE_NAME_STRING, top);
-    // Add arrays.
-    Type array = ts.addType(CAS.TYPE_NAME_ARRAY_BASE, top);
-    ts.arrayBaseType = (TypeImpl) array; // do here - used in next
-    ts.arrayBaseTypeCode = ts.arrayBaseType.getCode();
-    TypeImpl fsArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_FS_ARRAY, array);
-    ts.fsArrayType = fsArray; // do here - used in next
-    ts.fsArrayTypeCode = fsArray.getCode();
-    TypeImpl floatArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_FLOAT_ARRAY, array);
-    TypeImpl intArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_INTEGER_ARRAY, array);
-    TypeImpl stringArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_STRING_ARRAY, array);
-    // Add lists.
-    Type list = ts.addType(CAS.TYPE_NAME_LIST_BASE, top);
-    // FS lists.
-    Type fsList = ts.addType(CAS.TYPE_NAME_FS_LIST, list);
-    Type fsEList = ts.addType(CAS.TYPE_NAME_EMPTY_FS_LIST, fsList);
-    Type fsNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_FS_LIST, fsList);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, fsNeList, top, true);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, fsNeList, fsList, true);
-    // Float lists.
-    Type floatList = ts.addType(CAS.TYPE_NAME_FLOAT_LIST, list);
-    Type floatEList = ts.addType(CAS.TYPE_NAME_EMPTY_FLOAT_LIST, floatList);
-    Type floatNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_FLOAT_LIST, floatList);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, floatNeList, floatT, false);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, floatNeList, floatList, true);
-    // Integer lists.
-    Type intList = ts.addType(CAS.TYPE_NAME_INTEGER_LIST, list);
-    Type intEList = ts.addType(CAS.TYPE_NAME_EMPTY_INTEGER_LIST, intList);
-    Type intNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_INTEGER_LIST, intList);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, intNeList, intT, false);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, intNeList, intList, true);
-    // String lists.
-    Type stringList = ts.addType(CAS.TYPE_NAME_STRING_LIST, list);
-    Type stringEList = ts.addType(CAS.TYPE_NAME_EMPTY_STRING_LIST, stringList);
-    Type stringNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_STRING_LIST, stringList);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, stringNeList, stringT, false);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, stringNeList, stringList, true);
-
-    Type booleanT = ts.addType(CAS.TYPE_NAME_BOOLEAN, top);
-    Type byteT = ts.addType(CAS.TYPE_NAME_BYTE, top);
-    Type shortT = ts.addType(CAS.TYPE_NAME_SHORT, top);
-    Type longT = ts.addType(CAS.TYPE_NAME_LONG, top);
-    Type doubleT = ts.addType(CAS.TYPE_NAME_DOUBLE, top);
-
-    // array type initialization must follow the component type it's based on
-    TypeImpl booleanArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_BOOLEAN_ARRAY, array);
-    TypeImpl byteArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_BYTE_ARRAY, array);
-    TypeImpl shortArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_SHORT_ARRAY, array);
-    TypeImpl longArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_LONG_ARRAY, array);
-    TypeImpl doubleArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_DOUBLE_ARRAY, array);
-
-    // Sofa Stuff
-    Type sofa = ts.addType(CAS.TYPE_NAME_SOFA, top);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_SOFANUM, sofa, intT, false);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAID, sofa, stringT, false);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAMIME, sofa, stringT, false);
-    // Type localSofa = ts.addType(CAS.TYPE_NAME_LOCALSOFA, sofa);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAARRAY, sofa, top, true);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_SOFASTRING, sofa, stringT, false);
-    // Type remoteSofa = ts.addType(CAS.TYPE_NAME_REMOTESOFA, sofa);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAURI, sofa, stringT, false);
-
-    // Annotations
-    Type annotBaseType = ts.addType(CAS.TYPE_NAME_ANNOTATION_BASE, top);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_SOFA, annotBaseType, sofa, false);
-    Type annotType = ts.addType(CAS.TYPE_NAME_ANNOTATION, annotBaseType);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_BEGIN, annotType, intT, false);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_END, annotType, intT, false);
-    Type docType = ts.addType(CAS.TYPE_NAME_DOCUMENT_ANNOTATION, annotType);
-    ts.addFeature(CAS.FEATURE_BASE_NAME_LANGUAGE, docType, stringT, false);
-
-    // Lock individual types.
-    setTypeFinal(intT);
-    setTypeFinal(floatT);
-    setTypeFinal(stringT);
-    ((TypeImpl) top).setFeatureFinal();
-    setTypeFinal(array);
-    setTypeFinal(fsArray);
-    setTypeFinal(intArray);
-    setTypeFinal(floatArray);
-    setTypeFinal(stringArray);
-    setTypeFinal(sofa);
-
-    setTypeFinal(byteT);
-    setTypeFinal(booleanT);
-    setTypeFinal(shortT);
-    setTypeFinal(longT);
-    setTypeFinal(doubleT);
-    setTypeFinal(booleanArray);
-    setTypeFinal(byteArray);
-    setTypeFinal(shortArray);
-    setTypeFinal(longArray);
-    setTypeFinal(doubleArray);
-
-    ((TypeImpl) list).setFeatureFinal();
-    ((TypeImpl) fsList).setFeatureFinal();
-    ((TypeImpl) fsEList).setFeatureFinal();
-    ((TypeImpl) fsNeList).setFeatureFinal();
-    ((TypeImpl) floatList).setFeatureFinal();
-    ((TypeImpl) floatEList).setFeatureFinal();
-    ((TypeImpl) floatNeList).setFeatureFinal();
-    ((TypeImpl) intList).setFeatureFinal();
-    ((TypeImpl) intEList).setFeatureFinal();
-    ((TypeImpl) intNeList).setFeatureFinal();
-    ((TypeImpl) stringList).setFeatureFinal();
-    ((TypeImpl) stringEList).setFeatureFinal();
-    ((TypeImpl) stringNeList).setFeatureFinal();
-    ((TypeImpl) annotType).setFeatureFinal();
-    ((TypeImpl) annotBaseType).setFeatureFinal();
+    synchronized (ts) {
+      if (ts.areBuiltInTypesSetup) {
+        return;
+      }
+  
+      // W A R N I N G (July 2007)
+  
+      // C++ code has "hard-wired" the type code numbers for the
+      // built-in types, so you cannot change the order of the types
+      // Also, the complete serialization depends on the type-code numbers
+      // for the client and the server for the built-in types being
+      // the same.
+  
+      // The initialization code for types cannot depend on the type system
+      // having already been set up, because, obviously, it isn't set up (yet).
+  
+      // It is important to add types in a particular order and to set
+      // ts.xxx<type-name> and ts.xxx<type-name>code values so they are
+      // set before they're used. Some of the add-type logic is written
+      // to depend on the built-in types already having these values set.
+      // For example: addType ( ARRAY_BASE ) calls, eventually,
+      // ts.ll_isPrimitiveType -> ll_isRefType ->ll_getTypeClass -> ll_subsumes
+      // and along the way these are testing / comparing against type codes
+      // for built-in types which need to have been set.
+  
+      // Create top type.
+      Type top = ts.addTopType(CAS.TYPE_NAME_TOP);
+      // Add basic data types.
+      Type intT = ts.addType(CAS.TYPE_NAME_INTEGER, top);
+      Type floatT = ts.addType(CAS.TYPE_NAME_FLOAT, top);
+      Type stringT = ts.addType(CAS.TYPE_NAME_STRING, top);
+      // Add arrays.
+      Type array = ts.addType(CAS.TYPE_NAME_ARRAY_BASE, top);
+      ts.arrayBaseType = (TypeImpl) array; // do here - used in next
+      ts.arrayBaseTypeCode = ts.arrayBaseType.getCode();
+      TypeImpl fsArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_FS_ARRAY, array);
+      ts.fsArrayType = fsArray; // do here - used in next
+      ts.fsArrayTypeCode = fsArray.getCode();
+      TypeImpl floatArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_FLOAT_ARRAY, array);
+      TypeImpl intArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_INTEGER_ARRAY, array);
+      TypeImpl stringArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_STRING_ARRAY, array);
+      // Add lists.
+      Type list = ts.addType(CAS.TYPE_NAME_LIST_BASE, top);
+      // FS lists.
+      Type fsList = ts.addType(CAS.TYPE_NAME_FS_LIST, list);
+      Type fsEList = ts.addType(CAS.TYPE_NAME_EMPTY_FS_LIST, fsList);
+      Type fsNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_FS_LIST, fsList);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, fsNeList, top, true);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, fsNeList, fsList, true);
+      // Float lists.
+      Type floatList = ts.addType(CAS.TYPE_NAME_FLOAT_LIST, list);
+      Type floatEList = ts.addType(CAS.TYPE_NAME_EMPTY_FLOAT_LIST, floatList);
+      Type floatNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_FLOAT_LIST, floatList);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, floatNeList, floatT, false);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, floatNeList, floatList, true);
+      // Integer lists.
+      Type intList = ts.addType(CAS.TYPE_NAME_INTEGER_LIST, list);
+      Type intEList = ts.addType(CAS.TYPE_NAME_EMPTY_INTEGER_LIST, intList);
+      Type intNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_INTEGER_LIST, intList);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, intNeList, intT, false);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, intNeList, intList, true);
+      // String lists.
+      Type stringList = ts.addType(CAS.TYPE_NAME_STRING_LIST, list);
+      Type stringEList = ts.addType(CAS.TYPE_NAME_EMPTY_STRING_LIST, stringList);
+      Type stringNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_STRING_LIST, stringList);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, stringNeList, stringT, false);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, stringNeList, stringList, true);
+  
+      Type booleanT = ts.addType(CAS.TYPE_NAME_BOOLEAN, top);
+      Type byteT = ts.addType(CAS.TYPE_NAME_BYTE, top);
+      Type shortT = ts.addType(CAS.TYPE_NAME_SHORT, top);
+      Type longT = ts.addType(CAS.TYPE_NAME_LONG, top);
+      Type doubleT = ts.addType(CAS.TYPE_NAME_DOUBLE, top);
+  
+      // array type initialization must follow the component type it's based on
+      TypeImpl booleanArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_BOOLEAN_ARRAY, array);
+      TypeImpl byteArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_BYTE_ARRAY, array);
+      TypeImpl shortArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_SHORT_ARRAY, array);
+      TypeImpl longArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_LONG_ARRAY, array);
+      TypeImpl doubleArray = (TypeImpl) ts.addType(CAS.TYPE_NAME_DOUBLE_ARRAY, array);
+  
+      // Sofa Stuff
+      Type sofa = ts.addType(CAS.TYPE_NAME_SOFA, top);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_SOFANUM, sofa, intT, false);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAID, sofa, stringT, false);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAMIME, sofa, stringT, false);
+      // Type localSofa = ts.addType(CAS.TYPE_NAME_LOCALSOFA, sofa);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAARRAY, sofa, top, true);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_SOFASTRING, sofa, stringT, false);
+      // Type remoteSofa = ts.addType(CAS.TYPE_NAME_REMOTESOFA, sofa);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAURI, sofa, stringT, false);
+  
+      // Annotations
+      Type annotBaseType = ts.addType(CAS.TYPE_NAME_ANNOTATION_BASE, top);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_SOFA, annotBaseType, sofa, false);
+      Type annotType = ts.addType(CAS.TYPE_NAME_ANNOTATION, annotBaseType);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_BEGIN, annotType, intT, false);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_END, annotType, intT, false);
+      Type docType = ts.addType(CAS.TYPE_NAME_DOCUMENT_ANNOTATION, annotType);
+      ts.addFeature(CAS.FEATURE_BASE_NAME_LANGUAGE, docType, stringT, false);
+  
+      // Lock individual types.
+      setTypeFinal(intT);
+      setTypeFinal(floatT);
+      setTypeFinal(stringT);
+      ((TypeImpl) top).setFeatureFinal();
+      setTypeFinal(array);
+      setTypeFinal(fsArray);
+      setTypeFinal(intArray);
+      setTypeFinal(floatArray);
+      setTypeFinal(stringArray);
+      setTypeFinal(sofa);
+  
+      setTypeFinal(byteT);
+      setTypeFinal(booleanT);
+      setTypeFinal(shortT);
+      setTypeFinal(longT);
+      setTypeFinal(doubleT);
+      setTypeFinal(booleanArray);
+      setTypeFinal(byteArray);
+      setTypeFinal(shortArray);
+      setTypeFinal(longArray);
+      setTypeFinal(doubleArray);
+  
+      ((TypeImpl) list).setFeatureFinal();
+      ((TypeImpl) fsList).setFeatureFinal();
+      ((TypeImpl) fsEList).setFeatureFinal();
+      ((TypeImpl) fsNeList).setFeatureFinal();
+      ((TypeImpl) floatList).setFeatureFinal();
+      ((TypeImpl) floatEList).setFeatureFinal();
+      ((TypeImpl) floatNeList).setFeatureFinal();
+      ((TypeImpl) intList).setFeatureFinal();
+      ((TypeImpl) intEList).setFeatureFinal();
+      ((TypeImpl) intNeList).setFeatureFinal();
+      ((TypeImpl) stringList).setFeatureFinal();
+      ((TypeImpl) stringEList).setFeatureFinal();
+      ((TypeImpl) stringNeList).setFeatureFinal();
+      ((TypeImpl) annotType).setFeatureFinal();
+      ((TypeImpl) annotBaseType).setFeatureFinal();
+      // because this is volatile, there's a memory barrier that insures
+      // the things before happen before other reads 
+      // see http://stackoverflow.com/questions/13688697/is-a-write-to-a-volatile-a-memory-barrier-in-java
+      ts.areBuiltInTypesSetup = true;
+    } // end of sync block
   }
 
   private static void setTypeFinal(Type type) {

Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java?rev=1626379&r1=1626378&r2=1626379&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java Sat Sep 20 03:17:51 2014
@@ -215,7 +215,9 @@ public class TypeSystemImpl implements T
   // set up lazily
   TypeInfo[] typeInfoArray;
 
-  boolean areBuiltInTypesSetup = false;
+  // saw evidence that in some cases the setup is called on the same instance on two threads
+  // must be volatile to force the right memory barriers
+  volatile boolean areBuiltInTypesSetup = false;
 
   TypeImpl intType;