]> gerrit.simantics Code Review - simantics/fmil.git/commitdiff
Ensure unloadFMU is called only if FMU instance (pointer) exists 78/3778/1 release/1.42.0
authorMiro Richard Eklund <miro.eklund@semantum.fi>
Tue, 14 Jan 2020 10:50:50 +0000 (12:50 +0200)
committerMiro Richard Eklund <miro.eklund@semantum.fi>
Tue, 14 Jan 2020 10:50:50 +0000 (12:50 +0200)
Previous assumptions of unloadFMU was that there was a valid C-level
pointer to cleanup and pass to the FMU model's cleanup functions.
However, if only loadFMU is called prior to unloadFMU, then JVM would
crash with an access violation exception. I introduced a boolean for
instantiated to keep track of this to ensure we avoid future crashes if
unloadFMU is called directly after loadFMU.

gitlab #13

Change-Id: Idef742d6805e856617c3c95c0bb751d8a48caa0d

org.simantics.fmil.core/src/org/simantics/fmil/core/FMIL.java

index 4b1eeaca132386d9e1071b4e6bac3569d25d8325..ec63279c89feb1e982b3e79e254f77713afccac6 100644 (file)
@@ -184,7 +184,7 @@ public class FMIL {
      * @throws FMILException
      */
     private int fmuN = 0;
-    private boolean fmuLoaded = false;
+    private boolean instantiated = false;
     public void loadFMUFile(String path) throws FMILException {
 
         if (!Files.exists(Paths.get(path)))
@@ -229,8 +229,8 @@ public class FMIL {
                 for(int i=0;i<variableNames.length;i++) {
                        variableMap.put(variableNames[i], variableReferences[i]);
                 }
-
-                fmuLoaded = true;
+                
+                instantiated = false;
             } catch (UnsatisfiedLinkError err) {
                 throw new FMILException(UNSATISFIED_LINK, err);
             } catch (Exception e) {
@@ -278,9 +278,11 @@ public class FMIL {
             try {
 
                 int ret = instantiateSimulation_(getModelIDNew()); 
-                if(ret != OK)
+                if(ret != OK) {
                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
-
+                } else {
+                       instantiated = true;
+                }
             } catch (FMILException e) {
                 throw e;
             } catch (UnsatisfiedLinkError err) {
@@ -572,11 +574,15 @@ public class FMIL {
             try {
 
                 unlockFMUDirectory();
-                if(fmuLoaded) {
+                
+                // Many FMUs will not correctly clean-up during unload if the simulation isn't instantiated
+                // Essentially we'd likely be passing an invalid pointer to the FMU to cleanup, causing native c-level crashes.
+                
+                if(instantiated) {
                     int ret = unloadFMU_(getModelIDNew()); 
                     if(ret != OK)
                         LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
-                    fmuLoaded = false;
+                    instantiated = false;
                 }
                 removeFMUDirectoryContents();