Skip to content

Commit

Permalink
Improved unload of libs (help wine when dlopen / dlclose is supposed …
Browse files Browse the repository at this point in the history
…to unload the lib so it can be dlopen again)
  • Loading branch information
ptitSeb committed Mar 9, 2024
1 parent 378eb79 commit 3384640
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/elfs/elfloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down
17 changes: 12 additions & 5 deletions src/librarian/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
55 changes: 11 additions & 44 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/wrapped/wrappedlibc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion src/wrapped/wrappedlibdl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit 3384640

Please sign in to comment.