diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-03-09 14:10:09 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-03-09 14:10:09 +0100 |
| commit | 33846405d8e0af86bb5cfb9dab4ea5026fadb614 (patch) | |
| tree | 7fb9153caa2103fd0ec096472c542bcf4a4c6aea /src | |
| parent | 378eb79ad3ec58b4c19b3b38845cdb8a5db8dc5d (diff) | |
| download | box64-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.c | 4 | ||||
| -rw-r--r-- | src/librarian/library.c | 17 | ||||
| -rw-r--r-- | src/main.c | 55 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibc.c | 3 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibdl.c | 2 |
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; } |