about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-06-04 11:05:40 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-06-04 11:05:40 +0200
commitc6f6a9ef7249c63ad839fd0642df3a34e15bcf35 (patch)
tree33f5bc2174d813f6aecf34af5275f185a6ed608c /src
parent1c1e39ef644cda816e26f04ea63eb71919bb5942 (diff)
downloadbox64-c6f6a9ef7249c63ad839fd0642df3a34e15bcf35.tar.gz
box64-c6f6a9ef7249c63ad839fd0642df3a34e15bcf35.zip
Improved unloading of libs
Diffstat (limited to 'src')
-rwxr-xr-xsrc/librarian/librarian.c45
-rwxr-xr-xsrc/librarian/library.c12
-rwxr-xr-xsrc/tools/bridge.c2
3 files changed, 45 insertions, 14 deletions
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c
index 3273eeda..93344c9c 100755
--- a/src/librarian/librarian.c
+++ b/src/librarian/librarian.c
@@ -33,11 +33,12 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs)
 
     return maplib;
 }
-static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed) {
+static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed, library_t* owner) {
     if (freed[idx]) return; // Already freed
     
     freed[idx] = 1; // Avoid infinite loops
     library_t *lib = maplib->libraries[idx];
+    if(lib==owner) return; // don't free owner of maplib
     printf_log(LOG_DEBUG, "Free %s\n", lib->name);
     for (int i = lib->depended.size - 1; i >= 0; --i) {
         int j;
@@ -52,15 +53,15 @@ static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *free
             printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->depended.libs[i]->name);
             continue;
         }
-        freeLibraryRecurse(maplib, emu, j, freed);
+        freeLibraryRecurse(maplib, emu, j, freed, owner);
         if (freed[idx] != 1) {
             printf_log(LOG_DEBUG, "Library cleared (cyclic dependancy break)\n");
             return;
         }
     }
-    library_t *oldptr = maplib->libraries[idx];
-    Free1Library(&maplib->libraries[idx], emu);
-    maplib->libraries[idx] = oldptr; // Temporarily save the old address
+    library_t *ptr = maplib->libraries[idx];
+    if(maplib->ownlibs)
+        Free1Library(&ptr, emu);
     freed[idx] = 2;
 }
 void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
@@ -68,18 +69,21 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
     if(!maplib || !*maplib)
         return;
     
+    library_t* owner = (*maplib)->owner;
+    (*maplib)->owner = NULL;    // to avoid recursive free
     if((*maplib)->ownlibs && (*maplib)->libsz) {
         printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
         char *freed = (char*)calloc((*maplib)->libsz, sizeof(char));
         if (!freed) {
             printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n");
-            for (int i=(*maplib)->libsz-1; i>=0; --i) {
-                printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
-                Free1Library(&(*maplib)->libraries[i], emu);
-            }
+            for (int i=(*maplib)->libsz-1; i>=0; --i) 
+                if((*maplib)->libraries[i]!=owner) {
+                    printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
+                    Free1Library(&(*maplib)->libraries[i], emu);
+                }
         } else {
             for (int i=(*maplib)->libsz-1; i>=0; --i) {
-                freeLibraryRecurse(*maplib, emu, i, freed);
+                freeLibraryRecurse(*maplib, emu, i, freed, owner);
             }
             memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
             (*maplib)->libsz = 0;
@@ -193,6 +197,23 @@ void MapLibRemoveLib(lib_t* maplib, library_t* lib)
         memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx));
 }
 
+static void MapLibRemoveMapLib(lib_t* dest, lib_t* src)
+{
+    if(!src)
+        return;
+    //library_t *owner = src->owner;
+    for(int i=0; i<src->libsz; ++i) {
+        library_t* lib = src->libraries[i];
+        if(!lib || !libraryInMapLib(dest, lib)) continue;
+        MapLibRemoveLib(dest, lib);
+        if(lib->maplib && src!=lib->maplib && dest!=lib->maplib) {
+            MapLibRemoveMapLib(dest, lib->maplib);
+            if(lib->maplib && src==my_context->local_maplib)
+                lib->maplib = NULL;
+        }
+    }
+}
+
 int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu)
 {
     printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
@@ -216,6 +237,8 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
                 }
                 if(!libraryInMapLib(maplib, lib))
                     MapLibAddLib(maplib, lib);
+                if(maplib->ownlibs)
+                    MapLibRemoveMapLib(my_context->local_maplib, maplib);
             }
         } else {
             // promote lib from local to global...
@@ -227,7 +250,7 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
             }
             if(!libraryInMapLib(my_context->maplib, lib))
                 MapLibAddLib(my_context->maplib, lib);
-            MapLibRemoveLib(my_context->local_maplib, lib);
+            MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
         }
         add_neededlib(neededlibs, lib);
         if (lib && deplib) add_dependedlib(&lib->depended, deplib);
diff --git a/src/librarian/library.c b/src/librarian/library.c
index 4d2a1d22..1b858447 100755
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -249,13 +249,17 @@ library_t *NewLibrary(const char* path, box64context_t* context)
     printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
     if(box64_nopulse) {
         if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
-            Free1Library(&lib, NULL);
+            free(lib->name);
+            free(lib->path);
+            free(lib);
             return NULL;
         }
     }
     if(box64_novulkan) {
         if(strstr(lib->name, "libvulkan.so")==lib->name) {
-            Free1Library(&lib, NULL);
+            free(lib->name);
+            free(lib->path);
+            free(lib);
             return NULL;
         }
     }
@@ -273,7 +277,9 @@ library_t *NewLibrary(const char* path, box64context_t* context)
     // nothing loaded, so error...
     if(lib->type==-1)
     {
-        Free1Library(&lib, NULL);
+        free(lib->name);
+        free(lib->path);
+        free(lib);
         return NULL;
     }
 
diff --git a/src/tools/bridge.c b/src/tools/bridge.c
index 4bcdee0f..e05bb1a3 100755
--- a/src/tools/bridge.c
+++ b/src/tools/bridge.c
@@ -55,6 +55,8 @@ bridge_t *NewBridge()
 }
 void FreeBridge(bridge_t** bridge)
 {
+    if(!bridge || !*bridge)
+        return;
     brick_t *b = (*bridge)->head;
     while(b) {
         brick_t *n = b->next;