ecere/Android: Fixed: memory corruption after multiple onDestroy callbacks, mem leaks
authorJerome St-Louis <jerome@ecere.com>
Mon, 5 Nov 2012 06:08:42 +0000 (01:08 -0500)
committerJerome St-Louis <jerome@ecere.com>
Mon, 5 Nov 2012 06:08:42 +0000 (01:08 -0500)
- Fixed eInstance_Evolve to properly readjust classes when evolving from GuiApplication as well
- Now adjusting all classes throughout all modules when evolving
- Fixed Window class vs Application's Window classes pureVtbl mix up due to Skin selection before app was reloaded
   (Review copying of base window data into derived classes... pureVtbl is a class_data which really should not be copied)
- Fixed leaking GuiApplication which was constructed twice
- Cleaned up instance.ec global variables in __ecere_COM_Initialize() to support running with MemoryGuard
- Reviewed usage of __currentModule (-->__androidCurrentModule)/__thisModule in AndroidInterface.ec

ecere/src/com/instance.ec
ecere/src/gui/GuiApplication.ec
ecere/src/gui/drivers/AndroidInterface.ec
ecere/src/sys/Mutex.ec

index 97f5e8a..02e4165 100644 (file)
@@ -53,6 +53,12 @@ default:
 
 private:
 
+#if defined(__ANDROID__)
+#include <android/log.h>
+
+#define printf(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
+#endif
+
 #undef property
 #undef bool
 #undef uint
@@ -2435,6 +2441,7 @@ public dllexport Class eSystem_RegisterClass(ClassType type, char * name, char *
          if(totalSizeClass)
          {
             _class.data = renew _class.data byte[totalSizeClass];
+            // Class Data is often not inherited... e.g. Window::pureVtbl problem
             // memset(_class.data, 0, totalSizeClass);
             if(base && base.type != systemClass && base.type != enumClass)
                memcpy(_class.data, base.data, offsetClass);
@@ -4275,11 +4282,13 @@ public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
 {
    if(_class && instancePtr && *instancePtr)
    {
+      bool wasApp = false, wasGuiApp = false;
       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
       *instancePtr = instance;
       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
       // Fix pointers to application
-      if(!strcmp(instance._class.name, "Application"))
+      if((wasApp = !strcmp(instance._class.name, "Application")) ||
+         (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
       {
          Module module;
          Application app = (Application) instance;
@@ -4344,6 +4353,21 @@ public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
                template.module = _class.module;
             }
          }
+
+         for(module = app.allModules.first; module; module = module.next)
+         {
+            for(_class = module.classes.first; _class; _class = _class.next)
+            {
+               OldLink templateLink;
+               _class.module = module;
+               for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
+               {
+                  Class template = templateLink.data;
+                  template.module = _class.module;
+               }
+            }
+         }
+
          app.application = app;
       }
 
@@ -4357,11 +4381,29 @@ public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
       // Copy the virtual table initially
       instance._vTbl = _class._vTbl;
 
+      if(_class.Constructor)
+      {
+         if(!_class.Constructor(instance))
+         {
+            for(; _class; _class = _class.base)
+            {
+               if(_class.templateClass) _class = _class.templateClass;
+               if(_class.Destructor)
+                  _class.Destructor(instance);
+            }
+            _free(instance);
+            *instancePtr = null;
+         }
+      }
+      (_class.templateClass ? _class.templateClass : _class).count++;
+      // We don't want to reconstruct the portion already constructed...
+      /*
       if(!ConstructInstance(instance, _class))
       {
          _free(instance);
          *instancePtr = null;
       }
+      */
    }
 }
 
@@ -5952,6 +5994,21 @@ public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char
 {
    Application app;
 
+   // Clean up global variables
+   memoryInitialized = false;
+   pools = null;
+#ifdef MEMINFO
+   memset(&memStacks, 0, sizeof(BinaryTree));
+   memoryErrorsCount = 0;
+   memset(&memBlocks, 0, sizeof(BinaryTree));
+   recurse = false;
+   blockID = 0;
+   allocateClass = null;
+   allocateInternal = false;
+   TOTAL_MEM = 0;
+   OUTSIDE_MEM = 0;
+#endif
+
 #ifdef _DEBUG
    // printf("Using debug ecere runtime library\n");
 #endif
index 3c21ec4..9f8a47d 100644 (file)
@@ -1218,7 +1218,11 @@ public:
                      if(!link) skin = null;
 
                      if(skin)
+#if !defined(__ANDROID__)
                         SelectSkin(skin.name);
+#else
+                        currentSkin = skin;
+#endif
                   }
                }
 
index 613f4d2..c30934d 100644 (file)
@@ -348,7 +348,7 @@ static void onDestroy(ANativeActivity* activity)
    app.cleanup();
    app.Wait();
    delete androidActivity;
-   delete __currentModule;
+   delete __androidCurrentModule;
    LOGV("THE END.");
 }
 
@@ -470,6 +470,8 @@ default dllexport void ANativeActivity_onCreate(ANativeActivity* activity, void*
    guiApp = null;
    desktopW = 0; desktopH = 0;
    clipBoardData = null;
+   __thisModule = null;
+   __androidCurrentModule = null;
 
    LOGV("Creating: %p\n", activity);
 
@@ -484,9 +486,10 @@ default dllexport void ANativeActivity_onCreate(ANativeActivity* activity, void*
    androidArgv[0] = moduleName;
 
    // Create a base Application class
-   __thisModule = __currentModule = __ecere_COM_Initialize(true, 1, androidArgv);
+   __androidCurrentModule = __ecere_COM_Initialize(true, 1, androidArgv);
    // Load up Ecere
-   eModule_Load(__currentModule, "ecere", publicAccess);
+   eModule_Load(__androidCurrentModule, "ecere", publicAccess);
+
 
    if(activity->internalDataPath) PrintLn("internalDataPath is ", activity->internalDataPath);
    if(activity->externalDataPath) PrintLn("externalDataPath is ", activity->externalDataPath);
@@ -535,7 +538,7 @@ extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDo
 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
 private:
 
-static Module __currentModule;
+static Module __androidCurrentModule;
 static char * androidArgv[1];
 
 static int desktopW, desktopH;
@@ -1011,8 +1014,7 @@ class AndroidActivity : AndroidAppGlue
          Module app;
           
          // Evolve the Application class into a GuiApplication
-         eInstance_Evolve((Instance *)&__currentModule, class(GuiApplication));
-         __thisModule = __currentModule;
+         eInstance_Evolve((Instance *)&__androidCurrentModule, class(GuiApplication));
 
          // Wait for the initWindow command:
          guiApp.interfaceDriver = class(AndroidInterface);
@@ -1023,7 +1025,7 @@ class AndroidActivity : AndroidAppGlue
          }
 
          // Invoke __ecereDll_Load() in lib[our package name].so
-         app = eModule_Load(__currentModule, moduleName, publicAccess);
+         app = eModule_Load(__androidCurrentModule, moduleName, publicAccess);
          if(app)
          {
             Class c;
@@ -1032,12 +1034,17 @@ class AndroidActivity : AndroidAppGlue
             if(!c) c = class(GuiApplication);
 
             // Evolve the Application into it
-            eInstance_Evolve((Instance *)&__currentModule, c);
-            __thisModule = __currentModule;
+            eInstance_Evolve((Instance *)&__androidCurrentModule, c);
+            guiApp = (GuiApplication)__androidCurrentModule;
 
+            {
+               String skin = guiApp.skin;
+               *&guiApp.currentSkin = null;
+               guiApp.SelectSkin(skin);
+            }
 
             // Call Main()
-            __currentModule._vTbl[12](__currentModule);
+            __androidCurrentModule._vTbl[12](__androidCurrentModule);
          }
 
          if(!destroyRequested)
index 28f347c..a0ffb73 100644 (file)
@@ -21,7 +21,7 @@ public int GetCurrentThreadID()
 #if defined(__WIN32__)
    return (int)GetCurrentThreadId();
 #else
-   return pthread_self();
+   return (int)pthread_self();
 #endif
 }