about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-03-09 14:10:09 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-03-09 14:10:09 +0100
commit33846405d8e0af86bb5cfb9dab4ea5026fadb614 (patch)
tree7fb9153caa2103fd0ec096472c542bcf4a4c6aea /src
parent378eb79ad3ec58b4c19b3b38845cdb8a5db8dc5d (diff)
downloadbox64-33846405d8e0af86bb5cfb9dab4ea5026fadb614.tar.gz
box64-33846405d8e0af86bb5cfb9dab4ea5026fadb614.zip
Improved unload of libs (help wine when dlopen / dlclose is supposed to unload the lib so it can be dlopen again)
Diffstat (limited to 'src')
-rw-r--r--src/elfs/elfloader.c4
-rw-r--r--src/librarian/library.c17
-rw-r--r--src/main.c55
-rw-r--r--src/wrapped/wrappedlibc.c3
-rw-r--r--src/wrapped/wrappedlibdl.c2
5 files changed, 28 insertions, 53 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 93d3f224..860e819c 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -64,7 +64,7 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
         h->path[0] = '\0';
     }
     
-    h->refcnt = 1;
+    h->refcnt = 0;
 
     h->file = f;
     h->fileno = fileno(f);
@@ -1709,7 +1709,7 @@ EXPORT void PltResolver(x64emu_t* emu)
             GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, veropt, (void**)&elfsym);
     }
     if (!offs) {
-        printf_log(LOG_NONE, "Error: PltResolver: Symbol %s(%sver %d: %s%s%s) not found, cannot apply R_X86_64_JUMP_SLOT %p (%p) in %s\n", symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name);
+        printf_log(LOG_NONE, "Error: PltResolver: Symbol %s %s(%sver %d: %s%s%s) not found, cannot apply R_X86_64_JUMP_SLOT %p (%p) in %s (local_maplib=%p, global maplib=%p, deepbind=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":""), symname, veropt?"opt":"", version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name, local_maplib, my_context->maplib, deepbind);
         emu->quit = 1;
         return;
     } else {
diff --git a/src/librarian/library.c b/src/librarian/library.c
index fb27c430..f8c64c58 100644
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -575,6 +575,8 @@ void Free1Library(library_t **the_lib, x64emu_t* emu)
 
     library_t* lib = *the_lib;
 
+    FiniLibrary(lib, emu);
+
     printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name?:"???");
     // remove lib from maplib/local_maplib...
     if(my_context) {
@@ -585,10 +587,8 @@ void Free1Library(library_t **the_lib, x64emu_t* emu)
     int lib_type = lib->type;
     // Handle needed for cleaning
     needed_libs_t* needed = (lib_type==LIB_EMULATED && lib->e.elf)?lib->e.elf->needed:((lib_type==LIB_WRAPPED)?lib->w.needed:NULL);
-    // handle needed libs now
     if(needed)
-        for(int i=0; i<needed->size; ++i)
-            DecRefCount(&needed->libs[i], emu);
+        needed = copy_neededlib(needed);
     // free elf
     if(lib_type==LIB_EMULATED) {
         FreeElfHeader(&lib->e.elf);
@@ -636,6 +636,12 @@ void Free1Library(library_t **the_lib, x64emu_t* emu)
     //box_free(lib);
     if(*the_lib == lib)
         *the_lib = NULL;
+    // handle needed libs now
+    if(needed) {
+        for(int i=0; i<needed->size; ++i)
+            DecRefCount(&needed->libs[i], emu);
+        free_neededlib(needed);
+    }
 }
 
 char* GetNameLib(library_t* lib)
@@ -1219,8 +1225,10 @@ void setNeededLibs(library_t* lib, int n, ...)
 #define LIB_MAXCNT 255
 void IncRefCount(library_t* lib, x64emu_t* emu)
 {
-    if(!lib || lib->type==LIB_UNNKNOW)
+    if(!lib || lib->type==LIB_UNNKNOW) {
+        printf_log(LOG_NONE, "Warning, IncRefCount of a LIB_UNKNOWN library\n");
         return;
+    }
     switch (lib->type) {
         case LIB_WRAPPED:
             if(lib->w.refcnt==LIB_MAXCNT)
@@ -1261,7 +1269,6 @@ int DecRefCount(library_t** lib, x64emu_t* emu)
                 ret=--(*lib)->e.elf->refcnt;
             }
             if(!ret) {
-                FiniLibrary(*lib, emu);
                 Free1Library(lib, emu);
             }
             break;
diff --git a/src/main.c b/src/main.c
index f14b31a5..ccc46799 100644
--- a/src/main.c
+++ b/src/main.c
@@ -36,6 +36,8 @@
 #include "symbols.h"
 #include "rcfile.h"
 #include "emu/x64run_private.h"
+#include "elfs/elfloader_private.h"
+#include "library.h"
 
 box64context_t *my_context = NULL;
 int box64_quit = 0;
@@ -1479,9 +1481,6 @@ void endBox64()
     // then call all the fini
     dynarec_log(LOG_DEBUG, "endBox64() called\n");
     box64_quit = 1;
-    #ifndef STATICBUILD
-    endMallocHook();
-    #endif
     x64emu_t* emu = thread_get_emu();
     void startTimedExit();
     startTimedExit();
@@ -1490,50 +1489,18 @@ void endBox64()
     CallAllCleanup(emu);
     printf_log(LOG_DEBUG, "Calling fini for all loaded elfs and unload native libs\n");
     RunElfFini(my_context->elfs[0], emu);
-    FreeLibrarian(&my_context->local_maplib, emu);    // unload all libs
-    FreeLibrarian(&my_context->maplib, emu);    // unload all libs
     void closeAllDLOpenned();
     closeAllDLOpenned();    // close residual dlopenned libs
-    #if 0
-    // waiting for all thread except this one to finish
-    int this_thread = GetTID();
-    int pid = getpid();
-    int running = 1;
-    int attempt = 0;
-    printf_log(LOG_DEBUG, "Waiting for all threads to finish before unloading box64context\n");
-    while(running) {
-        DIR *proc_dir;
-        char dirname[100];
-        snprintf(dirname, sizeof dirname, "/proc/self/task");
-        proc_dir = opendir(dirname);
-        running = 0;
-        if (proc_dir)
-        {
-            struct dirent *entry;
-            while ((entry = readdir(proc_dir)) != NULL && !running)
-            {
-                if(entry->d_name[0] == '.')
-                    continue;
-
-                int tid = atoi(entry->d_name);
-                // tid != pthread_t, so no pthread functions are available here
-                if(tid!=this_thread) {
-                    if(attempt>4000) {
-                        printf_log(LOG_INFO, "Stop waiting for remaining thread %04d\n", tid);
-                        // enough wait, exit
-                        _exit(box64_exit_code);
-                    } else {
-                        running = 1;
-                        ++attempt;
-                        sched_yield();
-                    }
-                }
-            }
-            closedir(proc_dir);
-        }
-    }
-    #endif
+    // unload needed libs
+    needed_libs_t* needed = my_context->elfs[0]->needed;
+    printf_log(LOG_DEBUG, "Unloaded main elf: Will Dec RefCount of %d libs\n", needed?needed->size:0);
+    if(needed)
+        for(int i=0; i<needed->size; ++i)
+            DecRefCount(&needed->libs[i], emu);
     // all done, free context
+    #ifndef STATICBUILD
+    endMallocHook();
+    #endif
     FreeBox64Context(&my_context);
     #ifdef DYNAREC
     // disable dynarec now
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 0100385c..6ff9bab7 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -3440,7 +3440,8 @@ static void* timed_exit_thread(void* a)
 {
     // this is a workaround for some NVidia drivers on ARM64 that may freeze at exit
     // waiting on a pthread_cond_destroy
-    usleep(500000); // wait 1/2 a second
+    usleep(5000000); // wait 5 seconds
+    printf_log(LOG_DEBUG, "Too late, forced exit...\n");
     _exit(box64_exit_code); // force exit, something is wrong
 }
 
diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c
index 98d81034..c0f653b6 100644
--- a/src/wrapped/wrappedlibdl.c
+++ b/src/wrapped/wrappedlibdl.c
@@ -412,7 +412,7 @@ int my_dlclose(x64emu_t* emu, void *handle)
     }
     --dl->dllibs[nlib].count;
     elfheader_t* h = GetElf(dl->dllibs[nlib].lib);
-    if(!h || !h->gnuunique || actualy_closing)
+    if((h && !h->gnuunique) || !h || actualy_closing)
         DecRefCount(&dl->dllibs[nlib].lib, emu);
     return 0;
 }